P9744 「KDOI-06-S」消除序列

P9744 「KDOI-06-S」消除序列

比较优秀的一个题,也是难得可以算是场切绿的题。

首先你可以观察到如果你把一个序列都消成 00 的话,那么必然是选择一个位置使用 aa,剩下的位置仅可以用 bb,然后枚举选的位置得到最值,这是一个重要的观察。

原因显然,重复使用两个 aa 必然不优。

在这个基础上你就可以知道,对于每一次询问,你只用把使用 aa 覆盖后误删的位置(也就是需要保留 11 的位置)用 cc 还原回去,当前位置往后的如果是要求保留的,那么不使用 bb 即可。这个用个前缀和随便搞搞就行,是 O(qn)O(qn) 的。

考虑优化,观察到 m\sum mnn 同阶,从它去入手。观察相邻两个要保留 11 的位置之间怎么样快速计算出来答案。

对于相邻两个要保留 11 的两个位置之间,注意这两个位置之间的都要变成 00 他们在使用了一次 aa 以后,需要把误删的点 cc 加回去,这个值是固定的。然后发现在使用 bb 的时候,不需要使用 bb 的值也是固定的(也就是需要保留 11 的位置)。

那么对于使用 bb 的,我们只用需要用倘若从当前位置往后都使用 bb,减去需要保留 11 位置的 bb,就是后面的答案。

综合上面两个,我们可以在遍历相邻两个位置获得需要还原 cc 的答案,以及需要保留 bb 的答案。(这里的 bb 指的是该位置需要保留的 bb 值和,也就是误删的)只用保证中间位置的 a+ba+b (这里的 bb 指倘若从当前点往后都使用 bb 消去,无论是否保留),显然用个数据结构维护最小值即可。

其实重点就在这个完整的思考过程,感觉还是挺好的。

#include<bits/stdc++.h>
using namespace std;
const int N =1e6+10;
#define int long long 
int a[N],sum[N],b[N],c[N],sum0,sum1,sum2,p[N],Log[N],f[N][21];
bool vis[N];
int Query(int l,int r){
	int k=Log[r-l+1];
	return min(f[l][k],f[r-(1<<k)+1][k]);
}
signed main()
{
//	freopen("reserve4.in","r",stdin);
//	freopen("ans.out","w",stdout);
	memset(f,0x3f,sizeof(f));
	int n,q;
	cin>>n;
	for(int i=1;i<=n;i++)	scanf("%lld",&a[i]);
	for(int i=1;i<=n;i++)	scanf("%lld",&b[i]);
	for(int i=1;i<=n;i++)	scanf("%lld",&c[i]);
	for(int i=n;i>=1;i--)	sum[i]=sum[i+1]+b[i],f[i][0]=a[i]+sum[i+1],sum2+=b[i];
	for(int i=2;i<=n;i++)	Log[i]=Log[i>>1]+1;
	for(int j=1;j<=Log[n];j++)
		for(int i=1;i+(1<<j)-1<=n;i++)
			f[i][j]=min(f[i-1][j],f[i+(1<<(j-1))][j-1]);
	cin>>q;
	int lst=sum2;
	while(q--){
		sum2=lst;
		sum0=0,sum1=0;
		int ans=LONG_LONG_MAX;
		int m;
		cin>>m;
		for(int i=1;i<=m;i++)	scanf("%lld",&p[i]),sum0+=b[p[i]],sum2-=b[p[i]];
		if(m==n)	{cout<<0<<endl;continue;}
		if(m==0)	{cout<<Query(1,n)<<endl;continue;}
		int now=sum0;
		for(int i=1;i<m;i++){
			sum1+=c[p[i]];
			sum0-=b[p[i]];
			ans=min(ans,sum1+Query(p[i],p[i+1]-1)-sum0);
		}
		sum1+=c[p[m]];
		ans=min(ans,min(Query(1,p[1]-1)-now,sum1+Query(p[m],n)));
		ans=min(ans,sum2);
		printf("%lld\n",ans);
	}
	return 0;
}
// lst time text all.
posted @   June_Failure  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示