[bzoj2724] [Violet 6]蒲公英

  离散化+分块大法。

  在线询问区间众数。。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define ll long long
 7 #define us unsigned short
 8 using namespace std;
 9 const int maxn=40233,knum=233;
10 struct zs{int v,id;}a[maxn];
11 us pre[knum][maxn],ans[knum][maxn],sum[knum][maxn];
12 us num[maxn];
13 int l[knum],r[knum],bel[maxn],kuai;
14 int b[maxn],mp[maxn];
15 int i,j,k,n,m,cnt;
16  
17 int ra;char rx;
18 inline int read(){
19     rx=getchar(),ra=0;
20     while(rx<'0'||rx>'9')rx=getchar();
21     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
22 }
23 inline int query(int L,int R){
24     int j,idl=bel[L],idr=bel[R],mx=0,v=0,tmpmx,tmpv;register int i;
25     if(L==l[idl])return b[ans[idl][R]];
26     if(idl==idr){
27         for(i=L;i<=R;i++)
28             if(++num[mp[i]]==mx?mp[i]<v:num[mp[i]]>mx)mx=num[mp[i]],v=mp[i];
29         for(i=L;i<=R;i++)num[mp[i]]=0;
30         return b[v];
31     }
32     tmpmx=sum[idl+1][R],tmpv=ans[idl+1][R];
33     for(i=L;i<=r[idl];i++)num[mp[i]]++;tmpmx+=num[tmpv];
34     for(i=l[idr];i<=R;i++)num[mp[i]]++;
35     for(i=L;i<=r[idl];i++){
36         j=num[mp[i]]+pre[idr-1][mp[i]]-pre[idl][mp[i]];
37         if(j==tmpmx?mp[i]<tmpv:j>tmpmx)tmpmx=j,tmpv=mp[i];
38     }
39     for(i=L;i<=r[idl];i++)num[mp[i]]=0;
40     for(i=l[idr];i<=R;i++)num[mp[i]]=0;
41     return b[tmpv];
42 }
43 bool cmp(zs a,zs b){return a.v<b.v;}
44 int main(){
45     n=read(),m=read(),kuai=max(5,(int)sqrt(n)-20);
46     for(i=1;i<=n;i++)a[i].v=read(),a[i].id=i,bel[i]=(i+kuai-1)/kuai;
47     sort(a+1,a+1+n,cmp);
48     for(i=1;i<=n;mp[a[i].id]=cnt,i++)
49         if(a[i].v!=a[i-1].v)b[++cnt]=a[i].v;
50     for(i=1;i<=bel[n];i++)l[i]=(i-1)*kuai+1,r[i]=i==bel[n]?n:(l[i]+kuai-1);
51      
52     for(i=1;i<=bel[n];i++){
53         int mx=0,v=0;
54         for(j=l[i];j<=n;j++){
55             if(++num[mp[j]]==mx?mp[j]<v:num[mp[j]]>mx)mx=num[mp[j]],v=mp[j];
56             ans[i][j]=v,sum[i][j]=mx;
57         }
58         memset(num,0,(cnt+1)<<1);
59     }
60      
61     for(i=1;i<=n;i++){
62         num[mp[i]]++;
63         if(i==r[bel[i]])memcpy(pre[bel[i]],num,(cnt+1)<<1);
64     }memset(num,0,(cnt+1)<<1);
65     int last=0;
66     while(m--){
67         i=(read()+last-1)%n+1,j=(read()+last-1)%n+1;
68         if(i>j)swap(i,j);
69         printf("%d\n",last=query(i,j));
70     }
71 }
View Code

posted @ 2016-06-19 14:10  czllgzmzl  阅读(166)  评论(0编辑  收藏  举报