分块,因为没有修改的操作,在线询问,所以可以预处理出s[i][j]表示1到i块j出现的次数,f[i][j]表示i到j块有多少数出现次数为偶数,询问时两端的块暴力做一下就行了
题目卡空间(有毒),把块的大小调一下就没问题了
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 110000;
const int maxnn = 210;
int a[maxn],s[maxnn][maxn];
int id[maxn],L[maxnn],f[maxnn][maxnn];
int ti[maxn],ci[maxn],times;
int n,m,N,ki;
int main()
{
scanf("%d%d%d",&n,&ki,&m); N=500;
for(int i=1;i<=n;i++)
{
id[i]=(i-1)/N+1;
scanf("%d",&a[i]);
}
L[id[n]+1]=n+1;
for(int i=1;i<=id[n];i++) L[i]=(i-1)*N+1;
for(int i=1;i<=id[n];i++)
{
for(int j=1;j<=ki;j++) s[i][j]=s[i-1][j];
for(int j=L[i];j<L[i+1];j++) s[i][a[j]]++;
}
for(int i=1;i<=id[n];i++)
{
for(int j=i;j<=id[n];j++)
{
times++;
f[i][j]=f[i][j-1];
for(int l=L[j];l<L[j+1];l++)
{
if(ti[a[l]]!=times) ti[a[l]]=times,ci[a[l]]=0;
ci[a[l]]++;
int si=ci[a[l]]+s[j-1][a[l]]-s[i-1][a[l]];
if((si&1)&&si!=1) f[i][j]--;
if(!(si&1)) f[i][j]++;
}
}
}
int lastans=0;
while(m--)
{
int l,r; scanf("%d%d",&l,&r);
l=(l+lastans)%n+1; r=(r+lastans)%n+1;
if(l>r)swap(l,r);
int t1=id[l],t2=id[r];
int ret=0;
if(t1==t2)
{
times++;
for(int i=l;i<=r;i++)
{
if(ti[a[i]]!=times)ti[a[i]]=times,ci[a[i]]=0;
ci[a[i]]++;
if((ci[a[i]]&1)&&ci[a[i]]!=1)ret--;
if(!(ci[a[i]]&1))ret++;
}
}
else
{
ret=f[t1+1][t2-1];
times++;
for(int i=l;i<L[t1+1];i++)
{
if(ti[a[i]]!=times)ti[a[i]]=times,ci[a[i]]=0;
ci[a[i]]++;
int si=ci[a[i]]+s[t2-1][a[i]]-s[t1][a[i]];
if(si!=1&&(si&1))ret--;
if(!(si&1))ret++;
}
for(int i=L[t2];i<=r;i++)
{
if(ti[a[i]]!=times)ti[a[i]]=times,ci[a[i]]=0;
ci[a[i]]++;
int si=ci[a[i]]+s[t2-1][a[i]]-s[t1][a[i]];
if(si!=1&&(si&1))ret--;
if(!(si&1))ret++;
}
}
printf("%d\n",ret);
lastans=ret;
}
return 0;
}