題目鏈接:http://codeforces.com/contest/1082/problem/E
E. Increasing Frequency
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given array aa of length nn. You can choose one segment [l,r][l,r] (1≤l≤r≤n1≤l≤r≤n) and integer value kk (positive, negative or even zero) and change al,al+1,…,aral,al+1,…,ar by kk each (i.e. ai:=ai+kai:=ai+k for each l≤i≤rl≤i≤r).
What is the maximum possible number of elements with value cc that can be obtained after one such operation?
Input
The first line contains two integers nn and cc (1≤n≤5⋅1051≤n≤5⋅105, 1≤c≤5⋅1051≤c≤5⋅105) — the length of array and the value cc to obtain.
The second line contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤5⋅1051≤ai≤5⋅105) — array aa.
Output
Print one integer — the maximum possible number of elements with value cc which can be obtained after performing operation described above.
Examples
input
Copy
6 9 9 9 9 9 9 9
output
Copy
6
input
Copy
3 2 6 2 6
output
Copy
2
Note
In the first example we can choose any segment and k=0k=0. The array will stay same.
In the second example we can choose segment [1,3][1,3] and k=−4k=−4. The array will become [2,−2,2][2,−2,2].
題意:給你n(n<=1e5)個數和一個數c,你只能把一段連續區間裏的數都加上k(k由你自己定),使得整個序列含c儘可能的多。
思路:剛開始想線段樹、RMQ那邊去了,因爲顯然是從某處開始,前面的c的數量和後面的c的都已經確定,把中間這段數中出現次數最多的數都變成c。但是你要枚舉前面用了多少c,後面用了多少c已經是O(n*n),而且中間出現次數最多的數不好計算。於是我就自閉了。
看了別人的代碼瞬間醒悟。。。只需要dp一下就行了。
dp[i]表示從前面某個位置pos開始,到現在的位置i,把pos~i之間的(出現次數最多的)數變成c,前pos-1個不變的最大的含c的數量。
pre[x]=j表示對於某個數a[i]==x,它上一次出現的位置是j。即a[j]=a[i]=x。
qian[i]表示從第一個位置到當前位置i時c出現的次數。
hou[i]表示從最後一個位置到當前位置i時c出現的次數。
那麼狀態轉移方程就出來了:
dp[i]=max(qian[i-1]+1,dp[pre[a[i]]]+1);
pre[i]=i;
ans=max(ans,dp[i]+hou[i+1]);
這樣就可以保證某個位置pos開始,dp[pos+1]~dp[i]這一段出現次數最多的數都變成了c的最大的c的數量。
以上思路值得好好思考。
代碼:
#include<bits/stdc++.h>
#define ll long long
#define mp make_pair
using namespace std;
const int maxn=500000+10;
int n,k,m;
int cnt,tmp,flag,ans;
int dp[maxn];
int a[maxn],c[maxn],pre[maxn],qian[maxn],hou[maxn];
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
qian[i]=qian[i-1]+(a[i]==k);
}
for(int i=n;i>=1;i--)
{
hou[i]=hou[i+1]+(a[i]==k);
}
for(int i=1;i<=n;i++)
{
dp[i]=max(qian[i-1]+1,dp[pre[a[i]]]+1);
pre[a[i]]=i;
ans=max(ans,dp[i]+hou[i+1]);
}
printf("%d\n",ans);
return 0;
}