#线段树分治,背包#CF601E A Museum Robbery

题目

\(n\) 个展品正在被展览,每一个展品都有一价值 \(v\) 个和一个混乱度 \(w\) ,现在有 \(m\) 次操作:

1 \(v\) \(w\) :加入一个新的展品,价值为\(v\),混乱度为\(w\)

2 \(x\) :删除第\(x\)个展品(一开始的展品也参与编号,且保证此展品此时存在)

3 :进行询问

\(s(m)\) 为询问时混乱度之和不超过m的展品集合价值的最大值,
对于每一个询问,只需输出\(\sum_{m=1}^{k}s(m)*p^{m-1}\pmod q\)
其中,\(p=10^{7}+19,q=10^{9}+7\)


分析

删除操作很难做,考虑线段树分治,
对于每个时间点更新背包即可
时间复杂度\(O(mk\log_2 m)\)


代码

#include <cstdio>
#include <cctype>
#include <vector>
#include <cstring>
#define rr register
using namespace std;
const int mod=1000000007,p=10000019;
const int N=20011,M=1011;
struct rec{int c,w,l,r;}q[N];
int P[M],dp[M],n,m,T; vector<int>K[N<<2];
inline signed iut(){
	rr int ans=0,f=1; rr char c=getchar();
	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans*f;
}
inline void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline void update(int k,int l,int r,int x,int y,int z){
	if (l==x&&r==y) {K[k].push_back(z); return;}
	rr int mid=(l+r)>>1;
	if (y<=mid) update(k<<1,l,mid,x,y,z);
		else if (x>mid) update(k<<1|1,mid+1,r,x,y,z);
		    else update(k<<1,l,mid,x,mid,z),update(k<<1|1,mid+1,r,mid+1,y,z);
}
inline void dfs(int k,int l,int r){
	rr int len=K[k].size(),f[M];
	for (rr int i=0;i<len;++i){
		rr rec t=q[K[k][i]];
		for (rr int j=m;j>=t.w;--j)
		    dp[j]=max(dp[j],dp[j-t.w]+t.c);
	}
	if (l==r){
		rr int ans=0;
		for (rr int j=1;j<=m;++j)
		    ans=mo(ans,1ll*dp[j]*P[j-1]%mod);
		print(ans),putchar(10);
		return;
	}
	rr int mid=(l+r)>>1;
	memcpy(f,dp,sizeof(f));
	dfs(k<<1,l,mid);
	memcpy(dp,f,sizeof(dp));
	dfs(k<<1|1,mid+1,r);
}
signed main(){
	P[0]=1;
	for (rr int i=1;i<M;++i)
	    P[i]=1ll*P[i-1]*p%mod;
	n=iut(),m=iut();
	for (rr int i=1;i<=n;++i) q[i]=(rec){iut(),iut(),0,-2};
	for (rr int Q=iut();Q;--Q){
		rr int opt=iut();
		if (opt==3) ++T;
		else if (opt==1)
			q[++n]=(rec){iut(),iut(),T,-2};
		else q[iut()].r=T-1;
	}
	for (rr int i=1;i<=n;++i) if (q[i].r==-2) q[i].r=T-1;
	for (rr int i=1;i<=n;++i)
	    if (q[i].l<=q[i].r)
	        update(1,0,T-1,q[i].l,q[i].r,i);
	dfs(1,0,T-1);
	return 0;
}
posted @ 2021-07-07 10:46  lemondinosaur  阅读(67)  评论(0)    收藏  举报