其他分享
首页 > 其他分享> > 题解 CF601E A Museum Robbery

题解 CF601E A Museum Robbery

作者:互联网

分析

第一道线段树分治题祭。

线段树分治呢,处理的好像就是这些基于时间上的物品加入删除问题,我们将所有事件离线处理,每一个询问代表一个时刻,对于每一个物品,处理它所存在的时段,概括一下就是用线段树来处理每一个物品能对哪些询问起作用。

所以线段树每一个节点就代表了一个时段,而在询问中我们通常是找某一个时间点,所以类似于标记永久化的思想,在从上到下的过程中,如果能覆盖一个区间,那区间内的点也能同样造成影响,所以我们先将每一个物品加到它对应的区间,用 vector 存储完全覆盖某一区间的物品有哪些。

然后以此题为例,在从上到下的过程中将包含整个区间的物品从线段树中提出,再进行背包问题的处理,再将背包数组传给左右两区间,继续分治下去。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ls rt<<1
#define rs rt<<1|1
inline void read(int &res){
	res=0;
	int f=1;
	char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')res=(res<<1)+(res<<3)+c-48,c=getchar();
	res*=f;
}
const int base=1e7+19,mod=1e9+7;
int n,k,q,ti;
int csf[1005];
int l[15005],r[15005],v[15005],w[15005],cnt;
vector<int>V[120005];
void modify(int rt,int l,int r,int L,int R,int k){
	if(L>R)return;
	if(l>=L&&R>=r){
		V[rt].push_back(k);
		return;
	}
	int mid=(l+r)>>1;
	if(mid>=L)modify(ls,l,mid,L,R,k);
	if(mid<R)modify(rs,mid+1,r,L,R,k);
}
void solve(int rt,int l,int r,int f[]){
	for(int i=0;i<V[rt].size();i++){
		int x=V[rt][i];//提取物品 
		for(int j=k;j>=w[x];j--){//01背包 
			f[j]=max(f[j],f[j-w[x]]+v[x]);
		}
	}
	if(l==r){
		if(l==1)return;//起始点,因为ti初始为1线段树会方便一点,所以在这里多了一个特判 
		int b=1,sum=0;
		for(int i=1;i<=k;i++){
			sum=(sum+f[i]*b)%mod;
			b=b*base%mod;
		}
		printf("%lld\n",sum);
		return;
	}
	int mid=(l+r)>>1;
	int g[k+1];
	for(int i=0;i<=k;i++)g[i]=f[i];
	//这里下去会直接在子任务中修改f数组,所以不能直接将f传给右分治任务,所以新建g以存储 
	solve(ls,l,mid,f);
	solve(rs,mid+1,r,g);
}
signed main()
{
	read(n);read(k);
	cnt=n;
	ti=1;
	for(int i=1;i<=n;i++){
		read(v[i]);read(w[i]);
		l[i]=ti;//起始时间 
	}
	read(q);
	while(q--){
		int op,x,y,z;
		read(op);
		if(op==1){
			read(x);read(y);
			v[++cnt]=x;w[cnt]=y;
			l[cnt]=ti+1;//前面那个询问它管不到,所以+1 
		}
		else if(op==2){
			read(x);
			r[x]=ti;
		}
		else ti++;//多一询问,时间点++ 
	}
	for(int i=1;i<=cnt;i++){
		if(r[i])modify(1,1,ti,l[i],r[i],i);
		else modify(1,1,ti,l[i],ti,i);//寻找该物品所能完全覆盖的每一个最大区间,加入对应vector 
	}
	solve(1,1,ti,csf);//开始分治 
}

标签:return,int,题解,Museum,mid,区间,CF601E,物品,线段
来源: https://www.cnblogs.com/zxhmh/p/15698336.html