P11233 [CSP-S 2024] 染色(前缀和+动态规划)

P11233 [CSP-S 2024] 染色(前缀和+动态规划)

题目传送门

题意简介

将正整数序列染成两种颜色,第 \(i\) 个位置上的数若与左边最近的同色位置上的数相同,则可加上这个数的贡献,求染色后的最大贡献

思路

\(dp_i\) 表示前 \(i\) 个位置可以获得的最大贡献,首先有 \(dp_i=dp_{i-1}\) ,其次对于 \(a_i\) 上一次出现的位置 $last_{a_i} $ (在转移时动态维护),\(dp_i\) 也可以由这里转移过来,前提是 \([last_{a_i},i-1]\) 之间都是同色且与 \(i\) 异色,中间这一部分的贡献使用前缀和维护

Code

#include<iostream>
#include<cstring>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N=2e5+5;
const int MAXN=1e6+5;
int T,n,a[N],last[MAXN];
long long dp[N],pre[N];
int main()
{
    IOS;
    cin>>T;
    while(T--)
    {
        memset(dp,0,sizeof(dp));
        memset(pre,0,sizeof(pre));
        memset(last,0,sizeof(last));
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            if(a[i]==a[i-1]) pre[i]=pre[i-1]+a[i];
            else pre[i]=pre[i-1];//只有相邻两个同色位置值相同才会产生贡献
        }
        for(int i=1;i<=n;i++)
        {
            dp[i]=dp[i-1];
            if(last[a[i]]) dp[i]=max(dp[i],dp[last[a[i]]+1]+a[i]+pre[i]-pre[last[a[i]]+1]);
            //last[a[i]]+1处也可能会和更早的位置匹配产生贡献,如果从dp[last[a[i]]]转移默认last[a[i]]+1处只可能和后一位产生贡献
            last[a[i]]=i;
        }
        cout<<dp[n]<<'\n';
    }
    return 0;
}

完结撒花~

posted @ 2025-08-05 10:37  FallingGardenia  阅读(15)  评论(0)    收藏  举报