Loading

CF264C Choosing Balls

CF264C Choosing Balls

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

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

\[\begin{cases} a\times v_{d_i}&i\neq 1\text{且}c_{d_i}=c_{d_{i-1}}\\ b\times v_{d_i}&\text{otherwise} \end{cases} \]

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

直接用 multiset 模拟就是 \(O(qn\log 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\n",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);
	}
}
posted @ 2020-10-31 09:12  zzctommy  阅读(84)  评论(0编辑  收藏  举报