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次能选出的汉字的最多种类数。
分块。
首先预处理出任意连续的几段中出现偶数次的数字个数,以及每个数在序列中出现的位置下标。
对于在非整块中出现的数暴力统计,结合在整块中出现的次数讨论得出答案。
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
int a[100010],L[10010],R[10010],sta[100010],
tot[5010][5010],cnt[100010],last[100010],m,n,T;
vector<int> plc[100010];
vector<int>::iterator i1,i2;
int num(int x,int l,int r)
{
i1=lower_bound(plc[x].begin(),plc[x].end(),l);
i2=upper_bound(plc[x].begin(),plc[x].end(),r);
return i2-i1;
}
int rd()
{
int x=0;
char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x;
}
int main()
{
int c,i,j,k,p,q,x,y,z,ans,l,r,ll,rr,K,top,size;
scanf("%d%d%d",&n,&c,&m);
for (i=1;i<=n;i++)
{
a[i]=rd();
plc[a[i]].push_back(i);
}
size=sqrt((double)n/log(n)*log(2));
if (n%size) T=n/size+1;
else T=n/size;
for (i=1;i<=T;i++)
{
L[i]=R[i-1]+1;
R[i]=i==T?n:L[i]+size-1;
}
for (i=1;i<=T;i++)
{
for (j=i;j<=T;j++)
{
tot[i][j]=tot[i][j-1];
for (k=L[j];k<=R[j];k++)
{
if (last[a[k]]<i)
{
last[a[k]]=i;
cnt[a[k]]=1;
}
else cnt[a[k]]++;
if (cnt[a[k]]&1^1) tot[i][j]++;
else
{
if (cnt[a[k]]>1) tot[i][j]--;
}
}
}
}
ans=0;
memset(last,0,sizeof(last));
for (K=1;K<=m;K++)
{
l=rd();
r=rd();
l=(l+ans)%n+1;
r=(r+ans)%n+1;
if (l>r) swap(l,r);
ll=1;
while (L[ll]<l&&ll<=T) ll++;
rr=T;
while (R[rr]>r&&rr) rr--;
if (ll>rr)
{
ans=0;
for (i=l;i<=r;i++)
if (last[a[i]]<K)
{
last[a[i]]=K;
if (num(a[i],l,r)&1^1) ans++;
}
printf("%d\n",ans);
continue;
}
ans=tot[ll][rr];
top=0;
for (i=l;i<L[ll];i++)
if (last[a[i]]<K)
{
last[a[i]]=K;
sta[++top]=a[i];
}
for (i=R[rr]+1;i<=r;i++)
if (last[a[i]]<K)
{
last[a[i]]=K;
sta[++top]=a[i];
}
for (i=1;i<=top;i++)
{
x=num(sta[i],L[ll],R[rr]);
if (!x||(x&1))
{
if (num(sta[i],l,r)&1^1) ans++;
}
else
{
if (num(sta[i],l,r)&1) ans--;
}
}
printf("%d\n",ans);
}
}