BZOJ_2724_[Violet 6]蒲公英_分块

BZOJ_2724_[Violet 6]蒲公英_分块

Description

Input

修正一下

l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1

Output

Sample Input

6 3
1 2 3 2 1 2
1 5
3 6
1 5

Sample Output

1
2
1

HINT

n <= 40000, m <= 50000

 


 

对于众数,有一个性质。集合A和集合B的众数,要么是集合A的众数,要么是集合B中出现过的数。

根据这个性质我们考虑分块。

先将权值离散化,处理出前缀桶C[i][j]表示1~i块j数出现的次数。

在处理出mode[i][j]表示i块到j块的众数,这两个都可以在O(nsqrt(n))的时间内处理出来。

查询时众数来源有两个,所有整块的众数和零散块内出现过的数。

把零散的每个数统计一下,用桶可以O(1)得到答案。

 

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
#define N 40050
struct A {
    int num,id,v;
}a[N];
bool cmp1(const A &x,const A &y){return x.num<y.num;}
bool cmp2(const A &x,const A &y){return x.id<y.id;}
int n,m,block,pos[N],L[250],R[250],size,mode[250][250],C[250][N],mp[N],times[250][250],ans;
int h[N];
void solve(int l,int r) {
    int p=pos[l],q=pos[r];
    int md=0,i;
    if(p==q||p+1==q) {
        for(i=l;i<=r;i++) {
            h[a[i].v]++;
            if(h[a[i].v]>h[md]||(h[a[i].v]==h[md]&&a[i].v<md))
                md=a[i].v;
        }
        for(i=l;i<=r;i++) {
            h[a[i].v]=0;
        }
        ans=mp[md];
        return ;
    }
    int nowmode=mode[p+1][q-1],mtimes=times[p+1][q-1];
    h[nowmode]=mtimes;
    int tmp=nowmode;
    //printf("nowmode=%d, mtimes=%d\n",nowmode,mtimes); 
    for(i=l;i<=R[p];i++) {
        if(!h[a[i].v]) {
            h[a[i].v]=C[q-1][a[i].v]-C[p][a[i].v];
        }
        h[a[i].v]++;
        //printf("a[i].v=%d h[a[i].v]=%d\n",a[i].v,h[a[i].v]);
        if(h[a[i].v]>mtimes||(h[a[i].v]==mtimes&&a[i].v<nowmode)) {
            mtimes=h[a[i].v]; nowmode=a[i].v;
        }
    }
    for(i=L[q];i<=r;i++) {
        if(!h[a[i].v]) {
            h[a[i].v]=C[q-1][a[i].v]-C[p][a[i].v];
        }
        h[a[i].v]++;
        if(h[a[i].v]>mtimes||(h[a[i].v]==mtimes&&a[i].v<nowmode)) {
            mtimes=h[a[i].v]; nowmode=a[i].v;
        }
    }
    for(i=l;i<=R[p];i++) h[a[i].v]=0;
    for(i=L[q];i<=r;i++) h[a[i].v]=0;
    h[tmp]=0;
    ans=mp[nowmode];
}
int main() {
    scanf("%d%d",&n,&m);
    int i,j,k,x,y;
    for(i=1;i<=n;i++) scanf("%d",&a[i].num),a[i].id=i;
    sort(a+1,a+n+1,cmp1); a[0].num=342344354;
    for(i=1,j=0;i<=n;i++) {
        if(a[i].num!=a[i-1].num) j++;
        a[i].v=j;
        mp[j]=a[i].num;
    }
    sort(a+1,a+n+1,cmp2);
    size=sqrt(n);
    block=n/size;
    for(i=1;i<=block;i++) {
        L[i]=R[i-1]+1; R[i]=i*size;
        for(j=L[i];j<=R[i];j++) {
            pos[j]=i;
            /*if(!C[i][a[j].v]) {
                C[i][a[j].v]=C[i-1][a[j].v];
            }*/
            C[i][a[j].v]++;
        }
        for(j=1;j<=R[i];j++) {
            C[i+1][a[j].v]=C[i][a[j].v];
        }
    }
    if(R[block]!=n) {
        block++; L[block]=R[block-1]+1; R[block]=n;
        for(i=L[block];i<=n;i++) {
            pos[i]=block;
            /*if(!C[block][a[i].v]) {
                C[block][a[i].v]=C[block-1][a[i].v];
            }*/
            C[block][a[i].v]++;
        }
    }
    for(i=1;i<=block;i++) {
        int md=0;
        for(j=L[i];j<=R[i];j++) {
            if(C[i][a[j].v]-C[i-1][a[j].v]>C[i][md]-C[i-1][md]||(C[i][a[j].v]-C[i-1][a[j].v]==C[i][md]-C[i-1][md]&&a[j].v<md))
                md=a[j].v;
        }
        mode[i][i]=md; times[i][i]=C[i][md]-C[i-1][md];
        for(j=i+1;j<=block;j++) {
            int md=mode[i][j-1];
            for(k=L[j];k<=R[j];k++) {
                if(C[j][a[k].v]-C[i-1][a[k].v]>C[j][md]-C[i-1][md]||(C[j][a[k].v]-C[i-1][a[k].v]==C[j][md]-C[i-1][md]&&a[k].v<md))
                    md=a[k].v;
            }
            mode[i][j]=md; times[i][j]=C[j][md]-C[i-1][md];
        }
    }
    //for(i=1;i<=n;i++) printf("i=%d pos[i]=%d\n",i,pos[i]);
    while(m--) {
        scanf("%d%d",&x,&y);
        x=(x+ans-1)%n+1; y=(y+ans-1)%n+1;
        if(x>y) swap(x,y);
        solve(x,y);
        printf("%d\n",ans);
    }
}

 

posted @ 2018-04-14 14:31  fcwww  阅读(208)  评论(0编辑  收藏  举报