C139 线段树分治+01背包 CF601E A Museum Robbery

视频链接:C139 线段树分治+01背包 CF601E A Museum Robbery_哔哩哔哩_bilibili

 

 

 

E08【模板】背包DP 01背包 - 董晓 - 博客园 (cnblogs.com)

CF601E A Museum Robbery - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

// 线段树分治 O((n+q)*k*logq + qk)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define ll long long
#define ls (u<<1)
#define rs (u<<1|1)
#define mid ((l+r)>>1)
const int N=100005;
const ll P=1e7+19;
const ll Q=1e9+7;
int n,k,q;
ll f[N];
struct item{ //物品
  int l,r,v,w;
}e[N];
vector<item>tr[N<<2]; //节点

void insert(int u,int l,int r,int L,int R,int i){
  if(L>r||R<l) return;
  if(l>=L && r<=R)return tr[u].push_back(e[i]);
  insert(ls,l,mid,L,R,i);
  insert(rs,mid+1,r,L,R,i);
}
void solve(int u,int l,int r,ll *f){
  ll s[N];
  for(int i=1;i<=k;++i) s[i]=f[i];
  for(auto i:tr[u])
    for(int j=k;j>=i.w;--j)
      s[j]=max(s[j],s[j-i.w]+i.v);

  if(l==r){
    ll b=1,ans=0;
    for(int i=1;i<=k;i++){
      ans=(ans+s[i]*b)%Q;
      b=b*P%Q;
    }
    printf("%lld\n",ans);
  } 
  else solve(ls,l,mid,s),solve(rs,mid+1,r,s);
}
int main(){
  cin>>n>>k; int v,w,tot=0;
  for(int i=1;i<=n;++i){
    cin>>v>>w; //v价值 w质量
    e[++tot]={1,-1,v,w};
  }
  cin>>q; int cnt=0;
  for(int i=1,opt,x;i<=q;++i){
    cin>>opt;
    if(opt==1){ //添加
      cin>>v>>w;
      e[++tot]={cnt+1,-1,v,w};
    }
    if(opt==2){ //删除
      cin>>x;
      e[x].r=cnt; //x的结束时刻
    }
    if(opt==3)++cnt; //询问时刻
  }
  for(int i=1;i<=tot;++i){
    if(e[i].r==-1) e[i].r=cnt;
    insert(1,1,cnt,e[i].l,e[i].r,i);
  }
  solve(1,1,cnt,f);
}

 

posted @ 2024-06-16 21:35  董晓  阅读(111)  评论(1编辑  收藏  举报