ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 CF601E A Museum Robbery

2021-12-16 15:35:57  阅读:136  来源: 互联网

标签:return int 题解 Museum mid 区间 CF601E 物品 线段


分析

第一道线段树分治题祭。

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

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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有