P11233 [CSP-S 2024] 染色
[P11233 [CSP-S 2024] 染色]
说句闲话:考场没想到应该从last+1转移,怒调1.5h后20pts遗憾离场
我们记\(f_i\)为考虑到第i位时的答案,\(sum_i\)为[1,i]这个区间内在全染同种颜色时的贡献,\(last_i\)表示从i往左数,除本身之外第一个满足\(a_{last}=a_i\)的位置
形式化的sum: \(sum_x=\sum\limits_{i=2}^{x}[a_i=a_{i-1}]*a[i]\)
然后我们对于每个点i:f[i]=f[i-1];如果他有last:
f[i]=max(f[i],f[last+1]+s[i]-s[last+1]+a[i]);
我们考虑如何解释这个方程:
根据last的定义:
\( \left\{ \begin{array}{l} a[i] \ne a[j] | \forall j\in[last+1,i-1]\\ a[i]=a[last]\\ \end{array} \right. => col_{last}=col_{i}=0;col_{last+1}=col_{[last+1,i-1]}=1 \)
我们假设:
所以\(a[last]\ne a[last+1]\)
如果我们从last转移到i的话,\(last_{last_{i}+1}\)对于last_i+1的贡献就会被忽略,这样我们就不能使得答案最大化了
对于有last的i:
f[last+1]保证是在\(col[last]\ne col[last+1]\) 的时候取到的,所以我们在由last+1转移到i的时候能保证\(col[last]\ne col[i]\),二者结合:
\( \left\{ \begin{array}{l} col[last]\ne col[last+1]\\ col[last]\ne col[i] \\ \end{array} \right. => col[i]=col[last] \)
这样就保证了从f[last+1]转移到f[i]是合法的
然后这题就并不愉快的补完了
Code:
#include<bits/stdc++.h>
#define int long long
const int N=1e6+5;
using namespace std;
int a[N],last[N],f[N];
int n,inf;
int sum[N];
inline void upd(int &x,int y)
{
x = (x>y ? x : y);
}
void work()
{
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
last[a[i]]=0;f[i]=0;
sum[i]=sum[i-1];
sum[i]+= (a[i]==a[i-1] ? a[i] : 0);
}
for(int i=1;i<=n;i++)
{
f[i]=f[i-1];
if(last[a[i]])
{
int j=last[a[i]]+1;
upd(f[i],f[j]+a[i]+sum[i]-sum[j]);
}
last[a[i]]=i;
}
printf("%lld\n",f[n]);
}
#undef int
int main()
{
int T;
cin>>T;
while(T--)
{
work();
}
return 0;
}