RT,调了一天了,但是代码还是在 WA(0) 和 WA(20) 之间反复横跳。。。
555调了一天了,在线等大佬:
//2021/6/21
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int ma=100005;
const int maxn=5005;
int n,c,m;
int len,num;
int a[ma],l[ma],r[ma],pos[ma],t[ma];
int cnt[maxn][maxn],ans[maxn][maxn];
/*
l[i] 为第 i 块的左端点, r[i] 为第 i 块的右端点, pos[i] 为 i 点所在的块
len 为块的长度, num 为块的个数
cnt[i][j] 为前 i 块中 j 出现的次数
ans[i][j] 为第 i 块到第 j 块中 出现偶数次的数的个数
t[i] 为桶,每次用完清零
*/
inline int query(int le,int ri)
{
if(pos[le]+1>=pos[ri])
{
int s=0;
for(register int i=le;i<=ri;i++)
{
t[a[i]]++;
if((t[a[i]]%2)==0)
{
s++;
}
else if(t[a[i]]>=3)
{
s--;
}
}
for(register int i=le;i<=ri;i++)
{
t[a[i]]--;
}
return s;
}
else
{
int s=ans[pos[le]+1][pos[ri]-1];
for(register int i=le;i<=r[pos[le]];i++)
{
t[a[i]]++;
int tmp=cnt[pos[ri]-1][a[i]]-cnt[pos[le]][a[i]];
if(((t[a[i]]+tmp)%2)==0)
{
s++;
}
else if(t[a[i]]+tmp>=3)
{
s--;
}
}
for(register int i=l[pos[ri]];i<=ri;i++)
{
t[a[i]]++;
int tmp=cnt[pos[ri]-1][a[i]]-cnt[pos[le]][a[i]];
if(((t[a[i]]+tmp)%2)==0)
{
s++;
}
else if(t[a[i]]+tmp>=3)
{
s--;
}
}
for(register int i=le;i<=r[pos[le]];i++)
{
t[a[i]]--;
}
for(register int i=l[pos[ri]];i<=ri;i++)
{
t[a[i]]--;
}
return s;
}
}
int main(void)
{
scanf("%d%d%d",&n,&c,&m);
len=sqrt(n);
num=ceil(n/len);
for(register int i=1;i<=num;i++)
{
l[i]=(i-1)*len+1;
r[i]=i*len;
}
r[num]=n;
for(register int i=1;i<=len;i++)
{
for(register int j=l[i];j<=r[i];j++)
{
pos[j]=i;
}
}
for(register int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
cnt[pos[i]][a[i]]++;
}
for(register int i=1;i<=num;i++)
{
for(register int j=0;j<=c;j++)
{
cnt[i][j]+=cnt[i-1][j];
}
}
for(register int i=1;i<=num;i++)
{
for(register int j=i;j<=num;j++)
{
ans[i][j]=ans[i][j-1];
for(register int k=l[j];k<=r[j];k++)
{
t[a[k]]++;
if((t[a[k]]%2)==0)
{
ans[i][j]++;
}
else if(t[a[k]]>=3)
{
ans[i][j]--;
}
}
}
memset(t,0,sizeof(t));
}
int last=0;
while(m--)
{
int l,r;
scanf("%d%d",&l,&r);
int x,y;
x=(l+last)%n+1;
y=(r+last)%n+1;
if(x>y)
{
swap(x,y);
}
last=query(x,y);
printf("%d\n",last);
}
return 0;
}