CF1082E Increasing Frequency (multiset+亂搞+貪心)
阿新 • • 發佈:2018-12-04
題目大意:
QWQ
考場上真的**
想了好久都不會,直到考試快結束才知道怎麼做。
首先,根據題目,我們可以得知,假設我們修改了 這個區間,那麼最後的 就應該是總的m的個數,減去區間中m的個數,加上區間內的眾數的個數
QWQ
那麼我們考慮怎麼來處理這個。
首先,每個數字之間都是獨立的。
所以我們可以預處理每一個數字出現的位置。
然後假設當前我們要計算的數字是
那麼,我們可以先對於所有出現的位置 ,求一個 的答案QWQ
轉移的式子也是比較顯然。
其中
表示這段區間中的m的個數,這個可以用字首和來維護
dp[j]=dp[j-1]+1-(sum[v[i][j]]-sum[v[i][j-1]]);
那麼既然求出來這個東西,我們考慮左端點每移動一個,相當於對所有的右端點的區間加一個釋放出來的貢獻,也就是m的個數-1
所以說,我們現在需要一個能支援插入,刪除,字尾修改, 的一個數據結構
很自然能想到 ,插入刪除和max就不說了,字尾修改的話,我們只需要維護一個 表示改變數,對於每個元素,呼叫的時候都 就解決了
QWQ
給程式碼
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define mk makr_pair
#define ll long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 5e5+1e2;
int n,a[maxn];
int m;
int sum[maxn];
vector<int> v[maxn];
int cnt;
int vis[maxn];
int dp[maxn];
int ans;
int main()
{
n=read(),m=read();
for (int i=1;i<=n;i++) v[i].push_back(0);
for (int i=1;i<=n;i++)
{
a[i]=read();
if (!vis[a[i]])
{
++cnt;
vis[a[i]]=cnt;
}
v[vis[a[i]]].push_back(i);
}
for (int i=1;i<=n;i++) if(a[i]==m) sum[i]=1;
for (int i=1;i<=n;i++) sum[i]+=sum[i-1];
ans=sum[n];
for (int i=1;i<=cnt;i++)
{
if (a[v[i][1]]==m) continue;
int num = v[i].size();
multiset<int> s;
dp[1]=1;
s.insert(1);
for (int j=2;j<num;j++)
{
dp[j]=dp[j-1]+1-(sum[v[i][j]]-sum[v[i][j-1]]);
//cout<<j<<" "<<dp[j]<<endl;
s.insert(dp[j]);
}
ans=max(ans,(*(s.rbegin()))+sum[n]);
int j=1;
int delta=0;
while (j<num-1)
{
s.erase(s.find(dp[j]));
j++;
delta+=sum[v[i][j]]-sum[v[i][j-1]]-1;
ans=max(ans,(*(s.rbegin()))+delta+sum[n]);
}
}
cout<<ans;
return 0;
}