CF1082E Increasing Frequency
阿新 • • 發佈:2018-12-12
題意
給你一個長度為n的數列a,你可以任意選擇一個區間[L,R]並給區間每個數加上一個整數k,求這樣一次操作後數列中最多有多少個數等於c。
寫法比較巧妙的一個貪心題。
顯然可以想到相同的數字要放在一起來維護。
具體可以對每種數字開一個vector。然後列舉左端點,此時右端點的貢獻是一個只與右端點下標有關的式子。
差不多長這個樣子
(id[r]-id[l-1])-(s[r]-s[l-1])
顯然可以用線段樹來維護。
以上是自閉青年的做法。
考慮文藝青年會怎麼做:
既然一個區間的貢獻可以直接計算,那麼就直接O(n)掃描一遍,用dp陣列記錄當前每一種數字可以取到的價值最大的字首。
列舉到第i位時,顯然可以對dp[a[i]]做一個更新。
dp[a[i]]=max(dp[a[i]],s[i-1])+1;
然後,對每個時刻進行答案更新即可。ans=max(ans,dp[i]+s[n]-s[i]);
#include<iostream> #include<cctype> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<ctime> #include<cstdlib> #include<algorithm> #define N 1100000 #define L 1000000 #define eps 1e-7 #define inf 1e9+7 #define ll long long using namespace std; inline int read() { char ch=0; int x=0,flag=1; while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;} while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*flag; } int a[N],s[N],dp[N]; int main() { int n=read(),k=read(),ans=0; for(int i=1;i<=n;i++)a[i]=read(),s[i]=s[i-1]+(a[i]==k); for(int i=1;i<=n;i++) { dp[a[i]]=max(dp[a[i]],s[i-1])+1; ans=max(ans,dp[a[i]]+s[n]-s[i]); } printf("%d",max(ans,s[n])); return 0; }