题目链接: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;
}