洛谷P4168 蒲公英 分块处理区间众数模板( 二 )

处理单词询问时间复杂度为n1/2 。
算法整体复杂度为(m+n)*n1/2,即n3/2,可以通过本题 。
类似的题目还有  洛谷P4135。
#include<bits/stdc++.h>
using namespace std;const int h=40010;const int b_h=210;int len;int get_pos(int x){//得到某个位置所在分块编号    return (x-1)/len+1;}int n,m;int a[h],line[h];int ntot=0,num[h];map<int,int>rk;int tmp[h];int b_mos[b_h][b_h];int b_sum[b_h][h];void get_pre(){    for(int i=1;i<=get_pos(n);i++)        for(int j=1;j<=ntot;j++)            b_sum[i][j]+=b_sum[i-1][j];    for(int i=1;i<=get_pos(n);i++){        int mx=0;        for(int j=i;j<=get_pos(n);j++){            for(int k=(j-1)*len+1;k<=min(j*len,n);k++){                tmp[a[k]]++;                if(tmp[a[k]]>tmp[mx])                    mx=a[k];                if(!(tmp[a[k]]^tmp[mx]))                    mx=min(mx,a[k]);            }            b_mos[i][j]=mx;        }        for(int j=0;j<=ntot;j++)            tmp[j]=0;    }}int l,r,lb,rb,lst=0,ans;int get_vio(){    int mx=0;    for(int i=l;i<=r;i++){        tmp[a[i]]++;        if(tmp[a[i]]>tmp[mx])            mx=a[i];        if(tmp[a[i]]==tmp[mx])            mx=min(mx,a[i]);    }    for(int i=l;i<=r;i++)        tmp[a[i]]--;    return mx;}int get_tim(int x){//计算一个数的出现次数    return tmp[x]+b_sum[rb-1][x]-b_sum[lb][x];}int get_q(){    int mx=b_mos[lb+1][rb-1];    for(int i=l;i<=lb*len;i++){        tmp[a[i]]++;        if(get_tim(a[i])>get_tim(mx))            mx=a[i];        if(get_tim(a[i])==get_tim(mx))            mx=min(mx,a[i]);    }    for(int i=(rb-1)*len+1;i<=r;i++){        tmp[a[i]]++;        if(get_tim(a[i])>get_tim(mx))            mx=a[i];        if(get_tim(a[i])==get_tim(mx))            mx=min(mx,a[i]);    }    for(int i=l;i<=lb*len;i++)        tmp[a[i]]--;    for(int i=(rb-1)*len+1;i<=r;i++)        tmp[a[i]]--;    return mx;}int main(){    scanf("%d%d",&n,&m);    len=sqrt(n);    for(int i=1;i<=n;i++)        scanf("%d",&a[i]),line[i]=a[i];    sort(line+1,line+n+1);    for(int i=1;i<=n;i++)//离散化        if(line[i]!=line[i-1])            rk[line[i]]=++ntot,num[ntot]=line[i];    for(int i=1;i<=n;i++)        a[i]=rk[a[i]];    for(int i=1;i<=n;i++)        b_sum[get_pos(i)][a[i]]++;    get_pre();    for(int i=1;i<=m;i++){        scanf("%d%d",&l,&r);        l=(l+lst-1)%n+1,r=(r+lst-1)%n+1;        if(l>r)            swap(l,r);        lb=get_pos(l),rb=get_pos(r);        if(lb>=rb-1)            ans=get_vio();        else            ans=get_q();        printf("%d\n",num[ans]),lst=num[ans];    }    return 0;}

推荐阅读