BZOJ2821: 作诗(Poetize)

2821: 作诗(Poetize)

Time Limit: 50 Sec  Memory Limit: 128 MB
Submit: 1123  Solved: 354
[Submit][Status]

Description

神犇SJY虐完HEOI之后给傻×LYD出了一题:
SHY是T国的公主,平时的一大爱好是作诗。
由于时间紧迫,SHY作完诗之后还要虐OI,于是SHY找来一篇长度为N的文章,阅读M次,每次只阅读其中连续的一段[l,r],从这一段中选出一些汉字构成诗。因为SHY喜欢对偶,所以SHY规定最后选出的每个汉字都必须在[l,r]里出现了正偶数次。而且SHY认为选出的汉字的种类数(两个一样的汉字称为同一种)越多越好(为了拿到更多的素材!)。于是SHY请LYD安排选法。
LYD这种傻×当然不会了,于是向你请教……
问题简述:N个数,M组询问,每次问[l,r]中有多少个数出现正偶数次。

 

Input

输入第一行三个整数n、c以及m。表示文章字数、汉字的种类数、要选择M次。
第二行有n个整数,每个数Ai在[1, c]间,代表一个编码为Ai的汉字。
接下来m行每行两个整数l和r,设上一个询问的答案为ans(第一个询问时ans=0),令L=(l+ans)mod n+1, R=(r+ans)mod n+1,若L>R,交换L和R,则本次询问为[L,R]。

 

Output

输出共m行,每行一个整数,第i个数表示SHY第i次能选出的汉字的最多种类数。

 

Sample Input

5 3 5
1 2 2 3 1
0 4
1 2
2 2
2 3
3 5

Sample Output

2
0
0
0
1

HINT

 

对于100%的数据,1<=n,c,m<=10^5

 

Source

题解:
如果不强制在线的话可以用莫队来搞,强制在线的话就分块了。
相邻块里暴力,否则中间的大块的答案已知,考虑两小块对答案的影响,
可以用二分来求出小块内的元素在整个区间内出现的次数以及在中间大块中出现的次数,根据奇偶性来更新答案
因为大块的话,复杂度为O(块大小*logn),小块的复杂度为O(块大小)
如果每块为√n,可能会T,所以考虑把每块小一点,但又不能太小,选sqrt(n/logn)比较合适
代码:
  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<iostream>
  7 #include<vector>
  8 #include<map>
  9 #include<set>
 10 #include<queue>
 11 #include<string>
 12 #define inf 1000000000
 13 #define maxn 100000+1000
 14 #define maxm 2000
 15 #define eps 1e-10
 16 #define pa pair<int,int>
 17 #define for0(i,n) for(int i=0;i<=n;i++)
 18 #define for1(i,n) for(int i=1;i<=n;i++)
 19 #define for2(i,x,y) for(int i=x;i<=y;i++)
 20 using namespace std;
 21 inline int read()
 22 {
 23     int x=0,f=1;char ch=getchar();
 24     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 25     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 26     return x*f;
 27 }
 28 struct rec{int x,id;}b[maxn];
 29 int n,m,c,ans,block,a[maxn],l[maxn],r[maxn],pos[maxn],f[maxm][maxm],sum[maxn];
 30 bool mark[maxn];
 31 inline bool cmp(rec a,rec b)
 32 {
 33     return a.x<b.x||(a.x==b.x&&a.id<b.id);
 34 }
 35 inline int findup(int val,int pos)
 36 {
 37     int ll=l[val],rr=r[val],mid;
 38     while(ll<=rr)
 39     {
 40         mid=(ll+rr)>>1;
 41         if(b[mid].id>pos)rr=mid-1;else ll=mid+1;
 42     }
 43     return rr;
 44 }
 45 inline int finddown(int val,int pos)
 46 {
 47     int ll=l[val],rr=r[val],mid;
 48     while(ll<=rr)
 49     {
 50         mid=(ll+rr)>>1;
 51         if(b[mid].id>=pos)rr=mid-1;else ll=mid+1;
 52     }
 53     return ll;
 54 }  
 55 inline int find(int val,int x,int y)
 56 {
 57     return findup(val,y)-finddown(val,x)+1;
 58 }
 59 void ask(int x,int y)
 60 {
 61     x=(x+ans)%n+1;y=(y+ans)%n+1;if(x>y)swap(x,y);
 62     ans=0;
 63     int bx=pos[x],by=pos[y],r=bx*block,l=(by-1)*block+1,t1,t2;
 64     if(by-bx<=1)
 65     {
 66         for2(i,x,y)
 67           {
 68               sum[a[i]]++;
 69               if(sum[a[i]]&1&&sum[a[i]]!=1)ans--;
 70               if(!(sum[a[i]]&1))ans++;
 71           }
 72         for2(i,x,y)sum[a[i]]=0;  
 73     }
 74     else
 75     {
 76         ans=f[bx+1][by-1];
 77         for2(i,x,r)if(!mark[a[i]])
 78         {
 79             mark[a[i]]=1;
 80             t1=find(a[i],x,y);t2=find(a[i],r+1,l-1);
 81             if(t1&1&&!(t2&1)&&t2)ans--;
 82             if(!(t1&1)&&(t2&1||!t2))ans++;
 83         }
 84         for2(i,l,y)if(!mark[a[i]])
 85         {
 86             mark[a[i]]=1;
 87             t1=find(a[i],x,y);t2=find(a[i],r+1,l-1);
 88             if(t1&1&&!(t2&1)&&t2)ans--;
 89             if(!(t1&1)&&(t2&1||!t2))ans++;
 90         }
 91         for2(i,x,r)mark[a[i]]=0;
 92         for2(i,l,y)mark[a[i]]=0;
 93     }
 94      printf("%d\n",ans);
 95 }
 96 int main()
 97 {
 98     freopen("input.txt","r",stdin);
 99     freopen("output.txt","w",stdout);
100     n=read();c=read();m=read();
101     block=sqrt((double)n/log((double)n)*log(2));
102     for1(i,n)
103      {
104      a[i]=read();b[i].x=a[i];b[i].id=i;
105      pos[i]=(i-1)/block+1;
106      }
107     sort(b+1,b+n+1,cmp); 
108     for1(i,n+1)
109      if(b[i].x!=b[i-1].x)
110      {
111          r[b[i-1].x]=i-1;l[b[i].x]=i;
112      }
113     for1(i,pos[n])
114      {
115          ans=0;memset(sum,0,sizeof(sum));
116          for2(j,(i-1)*block+1,n)
117           {
118               sum[a[j]]++;
119               if(sum[a[j]]&1&&sum[a[j]]!=1)ans--;
120               if(!(sum[a[j]]&1))ans++;
121               f[i][pos[j]]=ans;
122           }
123      }
124     memset(sum,0,sizeof(sum)); 
125     ans=0;
126     while(m--)ask(read(),read());
127     return 0;
128 }
View Code

 

posted @ 2014-08-31 09:04  ZYF-ZYF  Views(201)  Comments(0Edit  收藏  举报