时空限制 1500ms-2500ms / 128MB
题目描述
神犇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次能选出的汉字的最多种类数。
说明
对于100%的数据,1<=n,c,m<=10^5
题目分析
这种维护没有区间相加性信息,又强制在线不能用莫队的题,一般就是分块了
s
u
m
[
i
]
[
x
]
sum[i][x]
sum[i][x]记录从块i开始到序列末尾种类为x的汉字的出现次数
c
n
t
[
i
]
[
j
]
cnt[i][j]
cnt[i][j]记录块i到块j的答案
预处理之后按分块套路分类讨论即可
卡常卡空间,卡到吐血
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long lt;
int read()
{
int f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
const int maxn=100010;
int n,m,c,t;
int a[maxn];
int sum[320][maxn],cnt[320][320];
int lft[320],rht[320],pos[maxn];
int rem[maxn],ans;
void build()
{
for(int i=1;i<=t;++i)
lft[i]=(i-1)*t+1,rht[i]=i*t;
if(rht[t]<n) t++,lft[t]=rht[t-1]+1,rht[t]=n;
for(int i=1;i<=t;++i)
for(int j=lft[i];j<=rht[i];++j)
pos[j]=i;
for(int i=1;i<=t;++i)
{
int tot=0;
for(int j=lft[i];j<=n;++j)
{
sum[i][a[j]]++;
if((sum[i][a[j]]&1)&&sum[i][a[j]]>1) tot--;
else if((sum[i][a[j]]&1)==0) tot++;
if(pos[j]!=pos[j+1]) cnt[i][pos[j]]=tot;
}
}
}
void cls(int ll,int rr)
{
for(int i=ll;i<=rr;++i) rem[a[i]]=0;
}
int solve(int ll,int rr)
{
int p=pos[ll],q=pos[rr],res=0;
if(q-p<=1)
{
for(int i=ll;i<=rr;++i)
{
rem[a[i]]++;
if((rem[a[i]]&1)==0) res++;
else if((rem[a[i]]&1)&&rem[a[i]]>1) res--;
}
cls(ll,rr);
}
else
{
int L,R;
res=cnt[p+1][q-1];
for(int i=ll;i<=rht[p];++i)
{
rem[a[i]]++;
int tt=rem[a[i]]+sum[p+1][a[i]]-sum[q][a[i]];
if((tt&1)&&tt>1) res--;
else if((tt&1)==0) res++;
}
for(int i=lft[q];i<=rr;++i)
{
rem[a[i]]++;
int tt=rem[a[i]]+sum[p+1][a[i]]-sum[q][a[i]];
if((tt&1)&&tt>1) res--;
else if((tt&1)==0) res++;
}
cls(ll,rht[p]); cls(lft[q],rr);
}
return res;
}
int main()
{
n=read();c=read();m=read();
for(int i=1;i<=n;++i) a[i]=read();
t=sqrt(n); build();
while(m--)
{
int ll=(read()+ans)%n+1,rr=(read()+ans)%n+1;
if(ll>rr) swap(ll,rr);
ans=solve(ll,rr);
printf("%d\n",ans);
}
return 0;
}