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 }

 

再一次被二分干掉了。。。

posted @ 2013-01-17 20:08  proverbs  阅读(1034)  评论(0编辑  收藏  举报