【分块】bzoj2821 作诗(Poetize)

分块,预处理出:

①第i块到第j块之间的偶数值的种类数。

②在前i块中,每个值出现的次数。(前缀和)(差分)

每次询问时,对于不在整块中的元素,进行暴力转移。

注意:减少memset的使用,千万不要写100000个memset,否则会TLE,宁愿每次询问之后O(sqrt(n))地一个个减掉那个记录每个值出现次数的临时数组。

Code:

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cmath>
  5 using namespace std;
  6 int n,kind,m,a[100001],sz,sum,num[100001],l[320],r[320],w[320][320];
  7 int Time[100001],ans,x,y;
  8 int ev[100001][320];
  9 void makeev()
 10 {
 11     for(int i=1;i<=n;i++)
 12       for(int j=num[i];j<=sum;j++)
 13         ev[a[i]][j]++;
 14 }
 15 inline int getsum(const int &v,const int &L,const int &R){return ev[v][R]-ev[v][L-1];}
 16 void makeblock()
 17 {
 18     for(sum=1;sum*sz<n;sum++)
 19       {
 20         l[sum]=(sum-1)*sz+1;
 21         r[sum]=sum*sz;
 22           for(int i=l[sum];i<=r[sum];i++)
 23           num[i]=sum;
 24       }
 25     l[sum]=sz*(sum-1)+1;
 26     r[sum]=n;
 27     for(int i=l[sum];i<=r[sum];i++)
 28       num[i]=sum;
 29 }
 30 void init()
 31 {
 32     for(int i=1;i<=sum;i++)
 33       {
 34           memset(Time,0,sizeof(Time));
 35           for(int j=i;j<=sum;j++)
 36           {
 37             w[i][j]=w[i][j-1];
 38             for(int k=l[j];k<=r[j];k++)
 39               {
 40                 Time[a[k]]++;
 41                 if(!(Time[a[k]]&1))w[i][j]++;
 42                 else if(Time[a[k]]!=1)w[i][j]--;
 43               }
 44           }
 45       }
 46 }
 47 int res,CH[20],Num;char c;
 48 inline int G()
 49 {
 50     res=0;c='*';
 51     while(c<'0'||c>'9')c=getchar();
 52     while(c>='0'&&c<='9'){res=res*10+(c-'0');c=getchar();}
 53     return res;
 54 }
 55 inline void P(int x)
 56 {
 57     if(!x){putchar('0');putchar('\n');return;}Num=0;  
 58     while(x>0){CH[++Num]=x%10;x/=10;}
 59     while(Num)putchar(CH[Num--]+48);
 60     putchar('\n');
 61 }
 62 int main()
 63 {
 64     n=G();kind=G();m=G();
 65     sz=sqrt(n);
 66     for(int i=1;i<=n;i++)a[i]=G();
 67     makeblock();init();makeev();
 68     memset(Time,0,sizeof(Time));
 69     for(int i=1;i<=m;i++)
 70       {
 71           x=G();y=G();x=(x+ans)%n+1;y=(y+ans)%n+1;if(x>y)swap(x,y);
 72         ans=w[num[x]+1][num[y]-1];
 73         if(num[x]+1>=num[y])
 74           {
 75               for(int j=x;j<=y;j++)
 76                 {
 77                     Time[a[j]]++;
 78                     if(!(Time[a[j]]&1))ans++;
 79                     else if(Time[a[j]]!=1)ans--;
 80                 }
 81               for(int j=x;j<=y;j++)Time[a[j]]--;
 82           }
 83         else
 84           {
 85               for(int j=x;j<=r[num[x]];j++)
 86               {
 87                   Time[a[j]]++;
 88                   if(!((Time[a[j]]+getsum(a[j],num[x]+1,num[y]-1))&1))ans++;
 89                   else if(Time[a[j]]+getsum(a[j],num[x]+1,num[y]-1)!=1)ans--;
 90               }
 91             for(int j=l[num[y]];j<=y;j++)
 92               {
 93                   Time[a[j]]++;
 94                   if(!((Time[a[j]]+getsum(a[j],num[x]+1,num[y]-1))&1))ans++;
 95                   else if(Time[a[j]]+getsum(a[j],num[x]+1,num[y]-1)!=1)ans--;
 96               }
 97               for(int j=x;j<=r[num[x]];j++)Time[a[j]]--;
 98               for(int j=l[num[y]];j<=y;j++)Time[a[j]]--;
 99           }
100         P(ans);
101       }
102     return 0;
103 }
posted @ 2014-09-09 20:48  AutSky_JadeK  阅读(255)  评论(2编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト