比较简单就简要说下做法吧:
题面上的翻译现在(10.31)是错的,讨论区那个翻译说得比较清楚转移方程都写上去了
设 \(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);
}
}