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;
}
posted @ 2024-10-29 21:40  liuboom  阅读(298)  评论(0)    收藏  举报