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;
}