難度範圍:[綠-紫]
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