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 }

 

 

你可能感兴趣的:(ZOJ)