莫队算法——(卡时间过的)

#include<bits/stdc++.h>
using namespace std;
inline void read(int &t){
    int f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()){
        if(c=='-')
            f=-1;
    }
    int ans=0;
    for(;isdigit(c);c=getchar()){
        ans=ans*10+c-'0';
    }
    t=ans;
}
typedef struct point{
    int l,r,ans,No;
}p;
const int N=200005;
int cnt[N],a[N],ans,block;
void add(int x){
    cnt[x]++;
    if(cnt[x]==1)  ans++;
}
void rem(int x){
    cnt[x]--;
    if(cnt[x]==0)  ans--;
}
bool cmp1(p a,p b){
    if((a.l/block)!=(b.l/block))
        return a.l<b.l;
    return a.r<b.r;
}
bool cmp2(p a,p b){
    return a.No<b.No;
}
int main()
{
    int n,q;
    while(~scanf("%d%d",&n,&q)){
        p P[N];
        memset(cnt,0,sizeof(cnt));
        for(int i=1;i<=n;i++){
            read(a[i]);
            a[i+n]=a[i];
        }
        for(int i=1;i<=q;i++){
            read(P[i].l),read(P[i].r);
            int tmp=P[i].r;
            P[i].r=P[i].l+n;
            P[i].l=tmp;
            P[i].No=i;
        }
        block=pow(q,0.6);
        sort(P+1,P+1+q,cmp1);

        int L=1,R=1;
        ans=0;
        add(a[1]);

        for(int i=1;i<=q;i++){
            while(L<P[i].l) {rem(a[L]);L++;}
            while(L>P[i].l) {L--;add(a[L]);}
            while(R<P[i].r) {R++;add(a[R]);}
            while(R>P[i].r) {rem(a[R]);R--;}
            P[i].ans=ans;
        }
        sort(P+1,P+1+q,cmp2);
        for(int i=1;i<=q;i++){
            printf("%d\n",P[i].ans);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/z_sea/article/details/81121934