BZOJ 2724 分块统计
区间众数
先离散化,学到了lagoon的lower_bound+unique的离散化,比我写的简单多了
预处理分成sqrt(n)块,记录d[i][j]和p[i][j]分别表示从i块起始位置到j块终止位置的众数出现次数和这个数是谁
开一个数组,记录每个数的位置,使得同类的相邻,同类数的坐标升序排列。
对于询问:
对于同一块内或者相邻块内的,直接暴力。
对于不同块内的,统计出非整块的区间内的所有出现过的数字,然后对这些数字在二分存储位置的数组,统计块内这个数出现的次数。然后结合d[i][j]和p[i][j]就可以得出答案了
View Code
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <cstdlib> 6 #include <cmath> 7 8 #define N 1000000 9 #define M 2000 10 11 using namespace std; 12 13 int sz,tot; 14 int lt[N],rt[N],ed[M],st[M],sum[N]; 15 int q[N],cs[N],p[M][M],d[M][M]; 16 int n,m; 17 int val[N],a[N]; 18 int ef[N]; 19 int bx,by; 20 21 inline void getblock() 22 { 23 sz=sqrt(n); tot=n/sz; 24 for(int i=1;i<=tot;i++) 25 { 26 st[i]=ed[i-1]+1; 27 ed[i]=st[i]+sz-1; 28 } 29 if(ed[tot]!=n) 30 { 31 ++tot; 32 st[tot]=ed[tot-1]+1; 33 ed[tot]=n; 34 } 35 int cnum,csum; 36 for(int i=1;i<=tot;i++) 37 { 38 csum=0; 39 memset(cs,0,sizeof cs); 40 for(int j=i;j<=tot;j++) 41 { 42 for(int k=st[j];k<=ed[j];k++) 43 { 44 cs[val[k]]++; 45 if(cs[val[k]]>csum) 46 { 47 csum=cs[val[k]]; 48 cnum=val[k]; 49 } 50 else if(cs[val[k]]==csum) 51 { 52 cnum=min(cnum,val[k]); 53 } 54 } 55 d[i][j]=csum; 56 p[i][j]=cnum; 57 } 58 } 59 } 60 61 inline void read() 62 { 63 scanf("%d%d",&n,&m); 64 for(int i=1;i<=n;i++) 65 { 66 scanf("%d",&val[i]); 67 a[i]=val[i]; 68 } 69 sort(a+1,a+1+n); 70 int num=unique(a+1,a+1+n)-a-1; 71 for(int i=1;i<=n;i++) 72 val[i]=lower_bound(a+1,a+1+num,val[i])-a; 73 for(int i=1;i<=n;i++) cs[val[i]]++; 74 for(int i=1;i<=num;i++) sum[i]=sum[i-1]+cs[i]; 75 for(int i=1;i<=num;i++) lt[i]=sum[i-1]+1,rt[i]=sum[i-1]; 76 for(int i=1;i<=n;i++) ef[++rt[val[i]]]=i; 77 78 getblock(); 79 } 80 81 inline int force(int x,int y) 82 { 83 for(int i=x;i<=y;i++) cs[val[i]]=0; 84 int cnum,csum=0; 85 for(int i=x;i<=y;i++) 86 { 87 cs[val[i]]++; 88 if(cs[val[i]]>csum) 89 { 90 csum=cs[val[i]]; 91 cnum=val[i]; 92 } 93 else if(cs[val[i]]==csum) 94 { 95 cnum=min(cnum,val[i]); 96 } 97 } 98 return cnum; 99 } 100 101 inline int getsum(int ll,int rr,int x) 102 { 103 return upper_bound(ef+rt[x-1]+1,ef+rt[x]+1,rr)-lower_bound(ef+rt[x-1]+1,ef+rt[x]+1,ll); 104 } 105 106 107 inline int query(int x,int y) 108 { 109 bx=x/sz+(x%sz!=0); 110 by=y/sz+(y%sz!=0); 111 if(bx==by||bx+1==by) return force(x,y); 112 113 int h=0; 114 for(int i=x;i<=ed[bx];i++) cs[val[i]]=0; 115 for(int i=st[by];i<=y;i++) cs[val[i]]=0; 116 for(int i=x;i<=ed[bx];i++) 117 { 118 cs[val[i]]++; 119 if(cs[val[i]]==1) q[++h]=val[i]; 120 } 121 for(int i=st[by];i<=y;i++) 122 { 123 cs[val[i]]++; 124 if(cs[val[i]]==1) q[++h]=val[i]; 125 } 126 bx++; by--; 127 int res=d[bx][by],ans=p[bx][by]; 128 for(int i=1;i<=h;i++) 129 { 130 int bnt=getsum(q[i]); 131 if(bnt+cs[q[i]]>res) 132 { 133 ans=q[i]; 134 res=bnt+cs[q[i]]; 135 } 136 else if(bnt+cs[q[i]]==res) 137 { 138 ans=min(ans,q[i]); 139 } 140 } 141 return ans; 142 } 143 144 inline void go() 145 { 146 int x,y,ans=0; 147 while(m--) 148 { 149 scanf("%d%d",&x,&y); 150 x=(x+ans-1)%n+1; y=(y+ans-1)%n+1; 151 if(x>y) swap(x,y); 152 ans=a[query(x,y)]; 153 printf("%d\n",ans); 154 } 155 } 156 157 int main() 158 { 159 read(); 160 go(); 161 return 0; 162 }
再一次被二分干掉了。。。
没有人能阻止我前进的步伐,除了我自己!