E. Increasing Frequency 最大子段和

发布时间 2023-09-16 18:57:16作者: 久远寺冇珠

 

题意:给你一个长度为n的数组,再给你一个c,问一次操作后,你最多能让数组中存在多少个c?

操作:选择一个区间,对这个区间加上任意整数。

做法:那么我们转化一下这个一题,就是要选择一个区间,使得该区间里有一个数,他的数量减去c的数量最大。这个其实就是一个最大子段和,我们数据范围内出现过的数每个都跑一遍最大子段和就好了。

需要注意一个细节,那就是我们这个最大子段和的写法是要改一点点的,就是在判断是否要修改左端点时,一般我会判断是否小于0。于是一直wa。最后发现,当小于等于0的时候,就一定要舍弃了,因为等于0的时候,我们舍弃左端点,转而让左端点成为现在的右端点,我们下次计算时多赚了一个点。

void solve(){
    int n,c;cin>>n>>c;
    vector<int>a(n+1);
    vector<vector<int>>pos(500010);
    vector<int>s(n+1);
    for(int i=1;i<=n;i++){
        cin>>a[i];pos[a[i]].push_back(i);
        s[i]=s[i-1];
        if(a[i]==c)s[i]++;
    }
    int ans=s[n];
    for(int k=1;k<=500000;k++){
        if(pos[k].size()==0||k==c)continue;
        int res=0;
        if(pos[k].size()==1){ans=max(ans,s[n]+1ll);continue;}
        int l=pos[k][0];
        int num=1;
        for(int i=1;i<pos[k].size();i++){
            num++;
            int res=num-(s[pos[k][i]]-s[l]);
            if(res<0){
                num=1;l=pos[k][i];
            }
            ans=max(ans,s[n]+res);
        }
    }
    cout<<ans<<"\n";

}