CF264C Choosing Balls(保留最大值、次大值+DP)

题意:

有n个球。它们排成一排。每个球都有一个颜色(为方便起见,为整数)和一个整数值。第i个球的颜色为ci,第i个球的值为vi。

松鼠Liss选择了一些球,并在不改变球相对顺序的情况下做出了新的顺序。她想最大化此序列的价值。

序列的值定义为每个球的以下值的总和(其中a和b为常数):

如果该球不在序列的开头,并且该球的颜色与上一个球的颜色相同,请添加(球的值)×a。
否则,加上(球的值)×b。
给出q个查询。每个查询包含两个整数ai和bi。对于每个查询,找到当a = ai和b = bi时她可以做出的序列的最大值。

请注意,新序列可以为空,并且空序列的值定义为零。

输入项
第一行包含两个整数n和q(1≤n≤105; 1≤q≤500)。第二行包含n个整数:v1,v2,...,vn(| vi |≤105)。第三行包含n个整数:c1,c2,...,cn(1≤ci≤n)。

接下来的q行包含查询的常量a和b的值。这些行的第i个包含两个整数ai和bi(| ai |,| bi |≤105)。

在每一行中,整数用单个空格分隔。

输出量
对于每个查询,输出包含整数的行-查询的答案。第i行按输入顺序包含第i个查询的答案。

请不要编写%lld说明符来以С++读取或写入64位整数。最好使用cin,cout流或%I64d说明符。

题解:

卡线段树。

/*
 *author: zlc
 *zucc_acm_lab
 *just do it
 */
#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const double pi=acos(-1.0);
const double eps=1e-6;
const int mod=1e9+7;
const ll inf=1e18;
const int maxn=1e6+100;
inline ll read () {ll x=0;ll f=1;char ch=getchar();while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}return x*f;}
//inline int read () {int x=0;int f=1;char ch=getchar();while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}return x*f;}
ll qpow (ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll n,m;
ll a[maxn];
ll c[maxn];
ll dp[maxn];
ll ans;
ll tot;
int main () {
    n=read();m=read();
    for (int i=1;i<=n;i++) a[i]=read();
    for (int i=1;i<=n;i++) c[i]=read();
    while (m--) {
        tot=0;
        ll u,v;
        u=read();v=read();
        for (int i=1;i<=n;i++) dp[i]=-inf; 
        ans=0;
        ll t1=0,t2=0;
        for (int i=1;i<=n;i++) {
            ans=max(v*a[i],dp[c[i]]+u*a[i]);
            if (c[i]!=t1) 
                ans=max(ans,dp[t1]+v*a[i]);
            else
                ans=max(ans,dp[t2]+v*a[i]);
            if (ans>dp[t1]) {
                if (t1!=c[i]) {
                    t2=t1;
                    t1=c[i];
                }
                else {
                    t1=c[i];
                }
            }
            else if (ans>dp[t2]&&c[i]!=t1) t2=c[i];
            dp[c[i]]=max(dp[c[i]],ans);
            tot=max(tot,ans);
        }
        printf("%lld
",tot);
    }
}
原文地址:https://www.cnblogs.com/zhanglichen/p/13648174.html