题目描述
神犇SJY虐完HEOI之后给傻×LYD出了一题:
SHY是T国的公主,平时的一大爱好是作诗。
由于时间紧迫,SHY作完诗之后还要虐OI,于是SHY找来一篇长度为N的文章,阅读M次,每次只阅读其中连续的一段[l,r],从这一段中选出一些汉字构成诗。因为SHY喜欢对偶,所以SHY规定最后选出的每个汉字都必须在[l,r]里出现了正偶数次。而且SHY认为选出的汉字的种类数(两个一样的汉字称为同一种)越多越好(为了拿到更多的素材!)。于是SHY请LYD安排选法。
LYD这种傻×当然不会了,于是向你请教……
问题简述:N个数,M组询问,每次问[l,r]中有多少个数出现正偶数次。
输入格式
输入第一行三个整数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]。
输出格式
输出共m行,每行一个整数,第i个数表示SHY第i次能选出的汉字的最多种类数。
预处理+分块
#include#define re return #define inc(i,l,r) for(int i=l;i<=r;++i) using namespace std; template inline void rd(T&x) { char c;bool f=0; while((c=getchar())<'0'||c>'9')if(c=='-')f=1; x=c^48; while((c=getchar())>='0'&&c<='9')x=x*10+(c^48); if(f)x=-x; } const int maxn=1e5+5; int n,m,c,T,siz; int a[maxn],cnt[maxn],belong[maxn],sum[320][maxn],ans[320][320]; int main() { rd(n),rd(c),rd(m); siz=sqrt(n); T=siz; if(T*T T; inc(i,1,n) { rd(a[i]); belong[i]=(i-1)/siz+1; ++sum[belong[i]][a[i]]; } inc(i,1,c) inc(j,1,T) sum[j][i]+=sum[j-1][i]; inc(i,2,T-1) { int now=0; inc(j,i,T-1) { for(int k=(j-1)*siz+1;k<=j*siz;++k) { ++cnt[a[k]]; if(!(cnt[a[k]]&1))++now; else if(cnt[a[k]]>2)--now; } ans[i][j]=now; } inc(j,(i-1)*siz+1,(T-1)*siz)cnt[a[j]]=0; } int kk=0,l,r,L,R; inc(i,1,m) { rd(l),rd(r); l=(l+kk)%n+1; r=(r+kk)%n+1; if(l>r)swap(l,r); kk=0; if(belong[r]<=belong[l]+1) { for(int j=l;j<=r;++j) { ++cnt[a[j]]; if(!(cnt[a[j]]&1))++kk; else if(cnt[a[j]]>2)--kk; } for(int j=l;j<=r;++j) cnt[a[j]]=0; } else { L=belong[l];R=belong[r]-1; kk=ans[belong[l]+1][R]; for(int j=l;j<=belong[l]*siz;++j) { ++cnt[a[j]]; if(!((cnt[a[j]]+sum[R][a[j]]-sum[L][a[j]])&1))++kk; else if((cnt[a[j]]+sum[R][a[j]]-sum[L][a[j]])>2)--kk; } for(int j=R*siz+1;j<=r;++j) { ++cnt[a[j]]; if(!(((cnt[a[j]]+sum[R][a[j]]-sum[L][a[j]]))&1))++kk; else if((cnt[a[j]]+sum[R][a[j]]-sum[L][a[j]])>2)--kk; } inc(j,l,belong[l]*siz)cnt[a[j]]=0; inc(j,R*siz+1,r)cnt[a[j]]=0; } printf("%d\n",kk); } re 0; }