E. Choosing Balls 夜

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

  

原文地址:https://www.cnblogs.com/liulangye/p/2870295.html