专栏文章

题解:P11233 [CSP-S 2024] 染色

P11233题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miqhj69s
此快照首次捕获于
2025/12/04 04:54
3 个月前
此快照最后确认于
2025/12/04 04:54
3 个月前
查看原文
思路比较简单,想完之后都怀疑自己想岔了,好歹是蓝题。

思路

先观察,容易发现想要结果最大,连续的相同数字一定是涂同色的,所以可以先预处理把连续的相同数字合并成一个,并将贡献的得分计算好。
然后得到一个任意相邻位置都不等的数列 aa。设 DiD_i 为在位置 ii 能取到的最大得分,对于任意一个位置 aia_i,都有放弃和得分两种情况:
  • 放弃 aia_i 很简单,就直接取前一个位置的最大得分 Di1D_{i-1} 就行了
  • 想要得分,先找到值 aia_i 在之前出现的最后位置 j(aj=ai,1j<i)j (a_j=a_i,1 \le j<i),这时需要满足条件:
  1. aia_iaja_j 同色
  2. jjii 之间(不含 jjii)的颜色相同,且都与 aia_iaja_j 不同
这意味着 jjii 之间只有 aj+1a_{j+1} 有可能得分,其他位置都不可能得分,所以位置 ii 得分只需要在 Dj+1D_{j+1} 基础上加上值 aia_i 就可以了。
最终 Di=max(Di1,Dj+1+ai)D_i=\max(D_{i-1},D_{j+1}+a_i),复杂度 O(n)O(n)

代码

CPP
#include<bits/stdc++.h>
using namespace std;
int T,n,A,last[1000005],pre[200005];
long long a[200005],dp[200005];
 
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>T;
	while(T--){
		cin>>n;
		memset(last,0,sizeof(last));
		int len=0;
		long long sum=0;
		for(int i=1;i<=n;i++){
			cin>>A;
			if(A==a[len]){//合并连续相同值
				sum+=A;
			}else{
				a[++len]=A;
				pre[len]=last[A];
				last[A]=len;
			}			
		}
		for(int i=2;i<=len;i++){
			dp[i]=pre[i]?max(dp[pre[i]+1]+a[i],dp[i-1]):dp[i-1];
		}
		cout<<sum+dp[len]<<endl;
	} 
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...