2024做題計劃

tomxi發表於2024-10-30

難度範圍:[綠-紫]

CSP-S2024 T3染色

首先動態規劃顯然,如何呢?不難設 \(f_{i}\) 表示對於前 \(i\) 個數來說的話,以 \(i\) 為結尾的答案的最大值,為啥是答案,因為這樣可以直接轉移 \(f_i=\max_{1\leq j<i}^{f_j+calc(j+1,i)+[a_j=a_i]\times a_i}\)
當然還有 \(f_i=\max{f_{i-1},f_i}\) 所以你就發現 \(f\) 有單調性,因為他可定大於等於上一個,然後你就發現答案就是 \(f_n\)。但是如果你直接轉移是 \(O(n^2)\) 很顯然會 TLE 。然後你發現如果有個 \(j\) 滿足 \(a_j\) 不等於 \(a_i\) 那麼會劣,那麼又因為 \(f\) 單調,所以 \(f_i\) 從前一個與 \(a_i\) 的值相等的位置轉移是不劣的,然後考慮開桶維護下上一次出現的位置就做完了!

程式碼:

#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

相關文章