首页 > 代码库 > 【分块】bzoj2724 [Violet 6]蒲公英

【分块】bzoj2724 [Violet 6]蒲公英

分块,离散化,预处理出:

①前i块中x出现的次数(差分);

②第i块到第j块中的众数是谁,出现了多少次。

询问的时候,对于整块的部分直接获得答案;对于零散的部分,暴力统计每个数出现的次数,加上差分的结果,尝试更新ans。

  1 #include<cstdio>  2 #include<cmath>  3 #include<algorithm>  4 #include<cstring>  5 using namespace std;  6 int n,m,sum,sz,num[40001],l[220],r[220],plv[40001][220],mode[220][220],mplv[220][220];  7 int a[40001],en,Time[40001],x,y,ma[40001],ans;  8 struct Point{int v,p;}b[40001];  9 bool operator < (const Point &a,const Point &b){return a.v<b.v;} 10 int Res,Num;char C,CH[12]; 11 inline int G() 12 { 13     Res=0;C=*; 14     while(C<0||C>9)C=getchar(); 15     while(C>=0&&C<=9){Res=Res*10+(C-0);C=getchar();} 16     return Res; 17 } 18 inline void P(int x) 19 { 20     Num=0;if(!x){putchar(0);puts("");return;} 21     while(x>0)CH[++Num]=x%10,x/=10; 22     while(Num)putchar(CH[Num--]+48); 23     puts(""); 24 } 25 void makeblock() 26 { 27     sz=(int)sqrt((double)n); if(!sz) sz=1; 28     for(sum=1;sum*sz<n;sum++) 29       { 30         l[sum]=r[sum-1]+1; 31         r[sum]=sum*sz; 32         for(int i=l[sum];i<=r[sum];i++) num[i]=sum; 33       } 34     l[sum]=r[sum-1]+1; 35     r[sum]=n; 36     for(int i=l[sum];i<=r[sum];i++) num[i]=sum; 37 } 38 void LiSan() 39 { 40     sort(b+1,b+n+1); 41     for(int i=1;i<=n;i++) 42       { 43         if(b[i].v!=b[i-1].v) en++; 44         ma[a[b[i].p]=en]=b[i].v; 45       } 46 } 47 void makeplv() 48 { 49     for(int i=1;i<=n;i++) 50       for(int j=num[i];j<=sum;j++) 51         plv[a[i]][j]++; 52 } 53 void makemode() 54 { 55     for(int i=1;i<=sum;i++) 56       { 57         memset(Time,0,sizeof(Time)); 58         int modenow,modeplv=0; 59         for(int j=i;j<=sum;j++) 60           { 61             for(int k=l[j];k<=r[j];k++) 62               { 63                 Time[a[k]]++; 64                 if(Time[a[k]]>modeplv||(Time[a[k]]==modeplv&&a[k]<modenow)) 65                   { 66                     modenow=a[k]; 67                     modeplv=Time[a[k]]; 68                   } 69               } 70             mode[i][j]=modenow; 71             mplv[i][j]=modeplv; 72           } 73       } memset(Time,0,sizeof(Time)); 74 } 75 int Getplv(const int &v,const int &L,const int &R){return plv[v][R]-plv[v][L-1];} 76 int main() 77 { 78     n=G(); m=G(); 79     for(int i=1;i<=n;i++) {b[i].v=G(); b[i].p=i;} 80     makeblock(); LiSan(); makeplv(); makemode(); 81     for(int i=1;i<=m;i++) 82       { 83         x=G(); y=G(); x=(x+ans-1)%n+1; y=(y+ans-1)%n+1; 84         if(x>y) swap(x,y); 85         int modenow,modeplv=0; 86         if(num[x]+1>=num[y]) 87           { 88             for(int j=x;j<=y;j++) 89               { 90                 Time[a[j]]++; 91                 if(Time[a[j]]>modeplv||(Time[a[j]]==modeplv&&a[j]<modenow)) 92                   { 93                     modenow=a[j]; 94                     modeplv=Time[a[j]]; 95                   } 96               } 97             for(int j=x;j<=y;j++) Time[a[j]]--; 98           } 99         else100           {101             modenow=mode[num[x]+1][num[y]-1];102             modeplv=mplv[num[x]+1][num[y]-1];103             for(int j=x;j<=r[num[x]];j++)104               {105                 Time[a[j]]++; int t=Time[a[j]]+Getplv(a[j],num[x]+1,num[y]-1);106                 if(t>modeplv||(t==modeplv&&a[j]<modenow))107                   {108                     modenow=a[j];109                     modeplv=t;110                   }111               }112             for(int j=l[num[y]];j<=y;j++)113               {114                 Time[a[j]]++; int t=Time[a[j]]+Getplv(a[j],num[x]+1,num[y]-1);115                 if(t>modeplv||(t==modeplv&&a[j]<modenow))116                   {117                     modenow=a[j];118                     modeplv=t;119                   }120               }121             for(int j=x;j<=r[num[x]];j++) Time[a[j]]--;122             for(int j=l[num[y]];j<=y;j++) Time[a[j]]--;123           }124         P(ans=ma[modenow]);125       }126     return 0;127 }

【分块】bzoj2724 [Violet 6]蒲公英