http://codeforces.com/contest/265/problem/E
每给定一组 a b 都要进行一次遍历 每次遍历将时间复杂度控制在 o(n)
每次遍历需要用到dp 思想
当遍历到 第 i 个位置时 假设第i中颜色 是k
f[k] 表示以k这种颜色 结尾时的最大值
以k颜色结尾时 其值可以使 b*v[i]
如果前面出现过相同颜色 还可能是 f[k] 或 f[k]+a*v[i]
如果前面出现过不同颜色 则取前面 最大的 结尾颜色 w 也可能是值 f[w]+b*v[i]
然后选最优就可以了
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<vector> #include<stack> #include<set> #include<map> #include<queue> #include<algorithm> #include<cmath> #define LL long long #define sint short int //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int N=100005; const int INF=0x3f3f3f3f; //typedef pair<int,int>point; LL v[N],f[N]; int c[N]; bool had[N]; LL solve(int n,LL a,LL b) { memset(had,false,sizeof(had)); int k1=-1,k2=-1; for(int i=1;i<=n;++i) { int k=c[i]; if(had[k]==false) { f[k]=b*v[i]; had[k]=true; }else { f[k]=max(max(f[k],f[k]+a*v[i]),b*v[i]); } if(k1!=-1&&k1!=k) f[k]=max(f[k],f[k1]+b*v[i]); else if(k2!=-1&&k2!=k) f[k]=max(f[k],f[k2]+b*v[i]); if(k!=k1&&k!=k2) { if(k2==-1||f[k2]<f[k]) k2=k; } if(k1==-1||f[k1]<f[k2]) swap(k1,k2); } LL ans=0; for(int i=0;i<N;++i) if(had[i]) ans=max(ans,f[i]); return ans; } int main() { //freopen("data.in","r",stdin); int n,q; while(scanf("%d %d",&n,&q)!=EOF) { for(int i=1;i<=n;++i) scanf("%I64d",&v[i]); for(int i=1;i<=n;++i) scanf("%d",&c[i]); while(q--) { LL a,b; scanf("%I64d %I64d",&a,&b); cout<<solve(n,a,b)<<endl; } } return 0; }