维护三种操作
1、加入一个重量为w,价值为v的物品
2、删除第k个加入的物品
3、求背包容量分别为1到m时可以获得的的最大价值
其中3用求和公式算出一个答案输出
这题我们可以考虑cdq分治
当做到区间[l,r]的时候,我们把所有起始位置<=l并且终止位置>r的物品加入背包
这样不断迭代到某个区间[l,l]的时候就可以直接查询答案了
维护哪些可以加入我是暴力传递vector的。这里可以用线段树来维护
#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct thing
{
int w,v;
int s,e;
}ch[100001];
long long p=10000019,mod=1000000007;
int f[31][1001];
int sx[100001];
int k;
inline void cale(int l,int r,int d,vector<int> q)
{
int i,j;
for(i=1;i<=k;i++)
f[d][i]=f[d-1][i];
for(i=0;i<q.size();i++)
{
// printf("%d ",q[i]);
if(ch[q[i]].s<=l&&ch[q[i]].e>=r)
{
for(j=k;j>=1;j--)
{
if(j>=ch[q[i]].w)
f[d][j]=max(f[d][j],f[d][j-ch[q[i]].w]+ch[q[i]].v);
}
}
}
// printf("\n\n");
if(l==r)
{
long long ans=0;
for(i=k;i>=1;i--)
ans=(ans*p+f[d][i])%mod;
for(i=1;i<=sx[l];i++)
printf("%I64d\n",ans);
}
else
{
int mid=(l+r)/2;
vector<int> ll,rr;
for(i=0;i<q.size();i++)
{
if(ch[q[i]].s<=l&&ch[q[i]].e>=r)
continue;
if(ch[q[i]].e<=mid)
ll.push_back(q[i]);
else if(ch[q[i]].s>mid)
rr.push_back(q[i]);
else
{
ll.push_back(q[i]);
rr.push_back(q[i]);
}
}
cale(l,mid,d+1,ll);
cale(mid+1,r,d+1,rr);
}
}
int main()
{
vector<int> q;
int n;
scanf("%d%d",&n,&k);
int i,j;
int v,w;
int tot=0,now=1;
for(i=1;i<=n;i++)
{
tot++;
scanf("%d%d",&ch[tot].v,&ch[tot].w);
ch[tot].s=now;
}
int qq;
scanf("%d",&qq);
int x;
for(i=1;i<=qq;i++)
{
scanf("%d",&x);
if(x==1)
{
tot++;
now++;
scanf("%d%d",&ch[tot].v,&ch[tot].w);
ch[tot].s=now;
}
else if(x==2)
{
scanf("%d",&x);
ch[x].e=now;
now++;
}
else
sx[now]++;
}
for(i=1;i<=tot;i++)
{
q.push_back(i);
if(ch[i].e==0)
ch[i].e=now;
}
cale(1,now,1,q);
return 0;
}