CF264C Choosing Balls

CF264C Choosing Balls

比较简单就简要说下做法吧:

题面上的翻译现在(10.31)是错的,讨论区那个翻译说得比较清楚转移方程都写上去了

[egin{cases} a imes v_{d_i}&i eq 1 ext{且}c_{d_i}=c_{d_{i-1}}\ b imes v_{d_i}& ext{otherwise} end{cases} ]

(dp_i) 表示选择 (i) 这个数的最大价值。

直接用 multiset 模拟就是 (O(qnlog n)) 的了。

方法是对于每个颜色记录最大的 (dp) 值,这样上面那行就可以做了。

multiset 存每种颜色最大的 (dp) 值,同时记录其颜色,当颜色不等于 (c_i) 时从下面那行转移。可以发现如果最大值的颜色等于 (c_i) ,那么multiset 里次大值的颜色一定不是 (c_i)

交上去 TLE on 8 ,意料之内。

由上述过程,我们发现 multiset 只是维护了 颜色不同的dp最大值和次大值

记录一下这两个东西,(O(1)) 更新即可

#define N 100005
int n,q,v[N],c[N];
LL dp[N],f[N];
void solve(int a,int b){
	memset(f,-0x3f,sizeof(f));
	f[0]=0;
	int id[2];
	id[0]=0,id[1]=-1;
	for(int i=1;i<=n;++i){
		dp[i]=f[c[i]]+1ll*a*v[i];
		if(id[0]!=c[i])dp[i]=max(dp[i],f[id[0]]+1ll*b*v[i]);
		else if(~id[1])dp[i]=max(dp[i],f[id[1]]+1ll*b*v[i]);
		if(dp[i]>f[c[i]]){
			f[c[i]]=dp[i];
			if(id[0]==c[i])continue;
			if(f[id[0]]<f[c[i]])id[1]=id[0],id[0]=c[i];
			else if(f[id[1]]<f[c[i]])id[1]=c[i];
		}
	}
	LL res=0;
	for(int i=0;i<=n;++i)res=max(res,dp[i]);
	printf("%lld
",res);
}
signed main(){
	n=read(),q=read();
	for(int i=1;i<=n;++i)v[i]=read();
	for(int i=1;i<=n;++i)c[i]=read();
	while(q--){
		int x=read(),y=read();
		solve(x,y);
	}
}
原文地址:https://www.cnblogs.com/zzctommy/p/13905165.html