CF1082E:E.increasing Frequency(贪心&最大连续和)

You are given array

What is the maximum possible number of elements with value

Input

The first line contains two integers

The second line contains

Output

Print one integer — the maximum possible number of elements with value

Examples
Input
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
",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
原文地址:https://www.cnblogs.com/hua-dong/p/10037989.html