[题解]P11233 [CSP-S 2024] 染色
设 \(f[i][j=0/1]\) 表示涂到第 \(i\) 位,且第 \(i\) 为颜色为 \(j\),则考虑用 \(i\) 之前能和 \(i\) 匹配的位置 \(p\) 进行转移。\(p\) 需要满足下面的条件:
- \(a[p]=a[i]\)。
- \(p\)的颜色为\(j\)。
- \([p+1,i-1]\)之间的颜色全不为\(j\)。
显然,我们只需要找满足条件的最大 \(p\) 即可,否则答案一定不是最优。所以我们直接维护 \(lst[i]=p\) 为 \(i\) 前面满足条件 \(1\) 的最大,要想满足条件 \(3\),我们还需要维护 \(g[l][r]\) 表示 \(l,r\) 这个区间全部同色时,该区间的答案,具体求法:
然后有 \(f\) 的转移(\(p\neq 0\) 时):
为什么是 \(f[p+1]\) 而不是 \(f[p]\)?因为 \([p+1,i-1]\) 中,有且仅有 \(p+1\) 可能对 \([1,p-1]\) 中的元素造成贡献,所以需要将 \(p-1\) 之前看作一段统计。
然后可以注意到 \(0\) 和 \(1\) 是对称的,所以砍掉第二维是可以的。
点击查看代码
#include<bits/stdc++.h>
#define N 200010
using namespace std;
int t,n,a[N],lst[N],f[N],g[2002][2002];
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
cin>>t;
while(t--){
memset(lst,0,sizeof lst);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
g[i][j]=g[i][j-1]+a[j]*(a[j-1]==a[j]);
}
}
for(int i=1;i<=n;i++){
f[i]=f[i-1];
if(lst[a[i]]) f[i]=max(f[i],f[lst[a[i]]+1]+a[i]+g[lst[a[i]]+1][i-1]);
lst[a[i]]=i;
}
cout<<f[n]<<"\n";
}
return 0;
}
时空复杂度都是 \(O(n^2)\) 的,瓶颈在于预处理 \(g\)。不难发现可以只保留 \(g[0]\) 作为 \(sum\),然后用前缀和的思想,将 \(g[x][y]\) 转为 \(sum[y]-sum[x]\) 即可。这是因为区间同色必须要求匹配的位置连续,而 \(sum[x]\) 表示 \((1,2)\sim(x-1,x)\) 的答案,\(sum[y]\) 则表示 \((1,2)\sim(y-1,y)\) 的答案,两者相减就是 \((x,x+1)\sim(y-1,y)\) 的答案。
注意 \(lst[i]=i-1\) 时,区间会出现 \(x>y\) 的情况,此时注意与 \(0\) 取 \(\max\)。
时空复杂度都为 \(O(n)\)。
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define V 1000010
#define N 200010
using namespace std;
int t,n,a[N],lst[V],f[N],g[N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
cin>>t;
while(t--){
memset(lst,0,sizeof lst);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=2;i<=n;i++) g[i]=g[i-1]+a[i]*(a[i-1]==a[i]);
for(int i=1;i<=n;i++){
f[i]=f[i-1];
if(lst[a[i]]){
f[i]=max(f[i],f[lst[a[i]]+1]+a[i]+max(g[i-1]-g[lst[a[i]]+1],0ll));
}
lst[a[i]]=i;
}
cout<<f[n]<<"\n";
}
return 0;
}
第 \(19\) 行,PassName的题解用
f[i]=max(f[i],f[lst[a[i]]+1]+a[i]+g[i]-g[lst[a[i]]+1]);
代替了
f[i]=max(f[i],f[lst[a[i]]+1]+a[i]+max(g[i-1]-g[lst[a[i]]+1],0ll));
这样也是可以的,因为:
- 当 \(a[i]=a[i-1]\) 时,\(g[i]-g[lst[a[i]]+1]=g[i]-g[i]=0\),而 \(g\) 是单调不降的,所以 \(g[i-1]-g[lst[a[i]]+1]\le 0\),取\(\max\)后同样 \(=0\)。
- 当 \(a[i]\neq a[i-1]\) 时,又有 \(g[i]=g[i-1]\),又 \((lst[a[i]]+1)\le (i-1)\),所以 \(g[lst[a[i]]+1]\le g[i-1]\),自然两式也相等。
感谢hanss6在此写法的理解上给我的帮助。
浙公网安备 33010602011771号