2024做题计划

难度范围:[绿-紫]

CSP-S2024 T3染色

首先动态规划显然,如何呢?不难设 fi 表示对于前 i 个数来说的话,以 i 为结尾的答案的最大值,为啥是答案,因为这样可以直接转移 fi=max1j<ifj+calc(j+1,i)+[aj=ai]×ai
当然还有 fi=maxfi1,fi 所以你就发现 f 有单调性,因为他可定大于等于上一个,然后你就发现答案就是 fn。但是如果你直接转移是 O(n2) 很显然会 TLE 。然后你发现如果有个 j 满足 aj 不等于 ai 那么会劣,那么又因为 f 单调,所以 fi 从前一个与 ai 的值相等的位置转移是不劣的,然后考虑开桶维护下上一次出现的位置就做完了!

代码:

#include<bits/stdc++.h>
using namespace std;
#define up(i,l,r) for(int i=l;i<=r;++i)
#define dn(i,l,r) for(int i=l;i>=r;--i)
#define int long long
const int N=2e5+5;
const int M=1e6+5;
int lst[M],a[N],n,f[N],pr[N],s[N];
inline void solve(){
	cin>>n;
	up(i,1,M-1) lst[i]=0;
	up(i,1,n){
		cin>>a[i];f[i]=0;s[i]=s[i-1]+(a[i]==a[i-1])*a[i];
		pr[i]=0;
	}
//	up(i,1,n) cout<<s[i]<<' ';
//	cout<<endl; 
	up(i,1,n){
		f[i]=f[i-1];pr[i]=lst[a[i]];
		if(lst[a[i]]){
			if(lst[a[i]]==i-1){
				f[i]=max(f[i],f[lst[a[i]]]+a[i]);
			}else{
				f[i]=max(f[i],f[lst[a[i]]+1]+a[i]+s[i]-s[lst[a[i]]+1]);
			}
		}
//		cout<<f[i]<<' ';
		lst[a[i]]=i;
	}
	cout<<f[n]<<'\n';
}
int32_t main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	int t;
	cin>>t;	
	while(t--) ::solve();
	return 0;
}
//tomxi
posted @   tomxi  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验
点击右上角即可分享
微信分享提示