D. Cut and Stick

经典莫队

解释一下 2x-len

x为超限的个数, len-x为好的个数

好块能容纳的个数为 len-x+1

剩下不能容纳的超限数的个数为x-(len-x+1)

单独划走一个是最优秀的

再加上 好的那块 就是2*x-len

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod = 1e9+7;
const int maxn = 2e6+10;
int n,m;
int ans[maxn],res,cnt[maxn],sum[maxn],a[maxn];
struct node{
    int l,r,qid,blo;
    int len(){
        return r-l+1;
    }
    bool operator<(const node&rhs)const{
        if(blo^rhs.blo)    return l<rhs.l;
        return blo & 1 ? r<rhs.r : rhs.r<r;
    }
}q[maxn];
void add(int x){
    sum[cnt[a[x]]]--;
    cnt[a[x]]++;
    res=max(res,cnt[a[x]]);
    sum[cnt[a[x]]]++;//个数的个数++ 
}
void del(int x){
    sum[cnt[a[x]]]--;
    if(sum[cnt[a[x]]]==0&&cnt[a[x]]==res)    res--;
    cnt[a[x]]--;
    sum[cnt[a[x]]]++; 
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=n;++i){
        cin>>a[i];
    }
    int block=(int)(sqrt(n>=3?n*(2.0/3):n));
    for(int i=1;i<=m;++i){
        cin>>q[i].l>>q[i].r;
        q[i].qid=i;
        q[i].blo=q[i].l/block;
    }
    sort(q+1,q+1+m);
    int l=0,r=0;
    for(int i =1;i<=m;++i){
        while(l < q[i].l)del(l++);
        while(l > q[i].l)add(--l);
        while(r < q[i].r)add(++r);
        while(r > q[i].r)del(r--);
        ans[q[i].qid ] = max(1,res*2-q[i].len());
    }
    for(int i=1;i<=m;++i)    printf("%d\n",ans[i]);
    return 0;
}

 

posted @ 2021-04-21 14:58  PdrEam  阅读(78)  评论(0编辑  收藏  举报