CF1082E:E.increasing Frequency(贪心&最大连续和)
You are given array
What is the maximum possible number of elements with value
InputThe first line contains two integers
The second line contains
OutputPrint one integer — the maximum possible number of elements with value
ExamplesInput
6 9 9 9 9 9 9 9
Output
6
Input
3 2 6 2 6
Output
2
题意:给定长度位N的序列,以及数字C,现在你可以给某个区间加一个数,使得最后这个序列的C个数最大,输出这个个数。
思路:假设我们在[L,R]这个区间加一个数(不为0),那么最后这个区间的贡献显然是众数减去这个区间原本为C的个数。
显然相同的数字一同考虑,考虑其贡献:每个数的贡献为1-到前一个的C的个数。
比如C=2; 那么1,2,3,2,1,5,第一个1的贡献是1,第二个1的贡献是-1,因为中间夹了两个C,即如果我们把1变为C,那么增加了一个C(1),但是减少了两个C(2)。
我们把每个数的贡献放到对应的数组里,然后就求“最大连续区间和”res。
而求最大连续区间和的过程,如果当前sum<1,舍去前一段,令sum=1,因为第一个pre是肯定可以做贡献为1的。 这里我wa了两发。其他地方还是蛮好想的。
下面的代码为为了避免负数,所有都加了一个Z=500000。
#include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=1000010; int a[maxn],b[maxn],Laxt[maxn],ans,N,C,res; vector<int>G[maxn]; int main() { scanf("%d%d",&N,&C); int Z=500000; rep(i,1,N) scanf("%d",&a[i]),a[i]=a[i]-C+Z; rep(i,1,N) { b[i]=b[i-1]; if(a[i]==Z) b[i]++; int pre=Laxt[a[i]]; if(pre==0) pre=i; G[a[i]].push_back(1-b[i]+b[pre]); Laxt[a[i]]=i; } ans=b[N]; rep(i,0,maxn-10) { if(i==Z) continue; int tmp=0; for(int j=0;j<G[i].size();j++){ tmp+=G[i][j]; res=max(tmp,res); if(tmp<=0) tmp=1; } } printf("%d\n",ans+res); return 0; } //8 4 4 0 0 4 2 1 0 4 //12 1 1 0 1 0 1 1 1 0 0 1 1 0
It is your time to fight!