普通莫队--洛谷P1997 【faebdc的烦恼】

离散化+莫队

cnt数组表示某个颜色出现的次数

sum数组表示某个数量出现的颜色种类

其它细节问题就按照莫队的模板来的

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
const int N=1e7+10;
struct E{
    int l,r,id;
}e[N*2];
int belong[N];
bool cmp(E a,E b){
    return (belong[a.l]^belong[b.l]) ? a.l<b.l : a.r<b.r;
}
int a[N];
int cnt[N],sum[N],op;
inline void add(int x){
    cnt[a[x]]++;
    sum[cnt[a[x]]]++;
    op=max(cnt[a[x]],op);
}
inline void del(int x){
    sum[cnt[a[x]]]--;
    if(sum[cnt[a[x]]]==0)op--;
    cnt[a[x]]--;
}
int ans[N];
int w[N];
int main(){
    int n,q;
    cin>>n>>q;
    int size=sqrt(n*2.0/3.0);
    int num=ceil((double)n/size);
    for(int i=1;i<=num;i++)
    for(int j=(i-1)*size+1;j<=i*size;j++)
    belong[j]=i;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        w[i]=a[i];
    }
    sort(w+1,w+1+n);
    int len=unique(w+1,w+n+1)-w-1;//去重
    for(int i=1;i<=n;i++)
    a[i]=lower_bound(w+1,w+1+len,a[i])-w;//离散化

    for(int i=1;i<=q;i++){
        scanf("%d%d",&e[i].l,&e[i].r);
        e[i].l=max(1,e[i].l);
        e[i].l=min(n,e[i].l);
        e[i].r=max(1,e[i].r);
        e[i].r=min(n,e[i].r);
        e[i].id=i;
    }
    sort(e+1,e+1+q,cmp);
    int l=e[1].l,r=e[1].r;
    for(int i=l;i<=r;i++)add(i);
    for(int i=1;i<=q;i++){
        while(l<e[i].l)del(l++);
        while(l>e[i].l)add(--l);
        while(r<e[i].r)add(++r);
        while(r>e[i].r)del(r--);
        ans[e[i].id]=op;
    }
    for(int i=1;i<=q;i++){
        printf("%d\n",ans[i]);
    }
}

猜你喜欢

转载自www.cnblogs.com/naruto-mzx/p/11323384.html