BZOJ 2821 分块统计

传说中的主席树可以做!ym zxr神犇~

此题目同:http://www.cnblogs.com/proverbs/archive/2013/01/17/2865123.html

 

View Code
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 #include <cmath>
  7 #include <ctime>
  8 
  9 #define N 100500
 10 #define M 2000
 11 
 12 using namespace std;
 13 
 14 int c[N],lt[N],rt[N],qz[N];
 15 int tot,sz;
 16 int st[N],ed[N];
 17 int cs[N],val[N];
 18 int d[M][M];
 19 int q[N];
 20 int n,pp,m,bx,by;
 21 
 22 inline void prev()
 23 {
 24     tot=(int)sqrt(1.0*n); sz=n/tot;
 25     for(int i=1;i<=tot;i++)
 26     {
 27         st[i]=ed[i-1]+1;
 28         ed[i]=st[i]+sz-1;
 29     }
 30     if(ed[tot]<n)
 31     {
 32         ++tot;
 33         st[tot]=ed[tot-1]+1;
 34         ed[tot]=n;
 35     }
 36     for(int i=1;i<=tot;i++)
 37     {
 38         int cnt=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]]&1)) cnt++;
 46                 else if(cs[val[k]]!=1) cnt--;
 47             }
 48             d[i][j]=cnt;
 49         }
 50     }    
 51 }
 52 
 53 inline void read()
 54 {
 55     memset(cs,0,sizeof cs);
 56     scanf("%d%d%d",&n,&pp,&m);
 57     for(int i=1,a;i<=n;i++)
 58     {
 59         scanf("%d",&val[i]);
 60         cs[val[i]]++;
 61     }
 62     
 63     for(int i=1;i<=pp;i++)
 64     {
 65         qz[i]=qz[i-1]+cs[i];
 66         lt[i]=qz[i-1]+1;rt[i]=qz[i-1];
 67     }
 68     for(int i=1;i<=n;i++)
 69         c[++rt[val[i]]]=i;
 70     prev();
 71 }
 72 
 73 inline int force(int x,int y)
 74 {
 75     for(int i=x;i<=y;i++) cs[val[i]]=0;
 76     int cnt=0;
 77     for(int i=x;i<=y;i++)
 78     {
 79         cs[val[i]]++;
 80         if(!(cs[val[i]]&1)) cnt++;
 81         else if(cs[val[i]]!=1) cnt--;
 82     }
 83     return cnt;
 84 }
 85 
 86 inline int getcnt(int ll,int rr,int x)
 87 {
 88     return upper_bound(c+rt[x-1]+1,c+rt[x]+1,rr)-lower_bound(c+rt[x-1]+1,c+rt[x]+1,ll);
 89 }
 90 
 91 inline int getans(int x,int y)
 92 {
 93     bx=(x+sz-1)/sz;
 94     by=(y+sz-1)/sz;
 95     if(bx==by||bx+1==by) return force(x,y);
 96     int h=0,ans=0;
 97     
 98     for(int i=x;i<=ed[bx];i++) cs[val[i]] = 0;
 99     for(int i=st[by];i<=y;i++) cs[val[i]] = 0;
100     
101     for(int i=x;i<=ed[bx];i++)
102     {
103         cs[val[i]]++;
104         if(cs[val[i]]==1) q[++h]=val[i];
105     }
106     for(int i=st[by];i<=y;i++)
107     {
108         cs[val[i]]++;
109         if(cs[val[i]]==1) q[++h]=val[i];
110     }
111     bx++; by--;
112     ans=d[bx][by];
113     for(int i=1,bnt;i<=h;i++)
114     {
115         bnt=getcnt(st[bx],ed[by],q[i]);
116         if(cs[q[i]]&1)
117         {
118             if(bnt&1) ans++;
119             else if(bnt!=0) ans--;
120         }
121         else
122         {
123             if(bnt==0) ans++;
124         }
125     }
126     return ans;
127 }
128 
129 inline void go()
130 {
131     int ans=0;
132     for(int i=1,a,b;i<=m;i++)
133     {
134         scanf("%d%d",&a,&b);
135         a=(a+ans)%n+1;
136         b=(b+ans)%n+1;
137         if(a>b) swap(a,b);
138         ans=getans(a,b);
139         printf("%d\n",ans);
140     }
141 }
142 
143 int main()
144 {
145     read();
146     go();
147     return 0;
148 }

 

 

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