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;
}
完结撒花~
浙公网安备 33010602011771号