题解:分块+双向链表
对于每个块维护块头的元素
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 100003
using namespace std;
int m,n,block;
int num[320][N],l[N],r[N],nxt[N],pre[N],belong[N];
int val[N];
void build(int x)
{
for (int i=l[x];i<=r[x];i++) num[x][val[i]]++;
}
int find(int x,int pos)
{
int now=l[pos];
while (x) {
x--;
now=nxt[now];
}
return now;
}
int main()
{
freopen("a.in","r",stdin);
freopen("my.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&val[i]),pre[i]=i-1,nxt[i]=i+1;
block=sqrt(n);
int t1=ceil(n*1.0/block);
for (int i=1;i<=n;i++) belong[i]=(i-1)/block+1;
for (int i=1;i<=t1;i++) l[i]=n+1,r[i]=0;
for (int i=1;i<=n;i++) {
int x=belong[i];
l[x]=min(l[x],i);
r[x]=max(r[x],i);
}
for (int i=1;i<=t1;i++) build(i);
scanf("%d",&m); int size=0;
for (int j=1;j<=m;j++) {
int opt,x,y,k,t;
scanf("%d%d%d",&opt,&x,&y);
x=(x+size-1)%n+1; y=(y+size-1)%n+1;
if (x>y) swap(x,y);
int b1=(x-1)/block+1; int b2=(y-1)/block+1;
x=find(x-(b1-1)*block-1,b1); y=find(y-(b2-1)*block-1,b2);
// cout<<x<<" "<<y<<endl;
if (opt==1) {
if (x==y) continue;
int lx=l[b1]; int ly=l[b2];
if (lx==x) l[b1]=y;
for (int i=b2;i>=b1+1;i--){
l[i]=pre[l[i]];
num[i-1][val[l[i]]]--;
num[i][val[l[i]]]++;
}
num[b2][val[y]]--; num[b1][val[y]]++;
t=pre[y]; nxt[t]=nxt[y]; pre[nxt[y]]=t;
t=pre[x]; nxt[t]=y; pre[y]=t;
nxt[y]=x; pre[x]=y;
}
else {
scanf("%d",&k); k=(k+size-1)%n+1;
size=0;
if (b1==b2) {
for (int i=x;i!=y;i=nxt[i])
if (val[i]==k) size++;
if (val[y]==k) size++;
printf("%d\n",size);
continue;
}
int rx=find(min(block,n-(b1-1)*block)-1,b1);
for (int i=x;i!=rx;i=nxt[i])
if (val[i]==k) size++;
if (val[rx]==k) size++;
for (int i=l[b2];i!=y;i=nxt[i])
if (val[i]==k) size++;
if (val[y]==k) size++;
for (int i=b1+1;i<=b2-1;i++) size+=num[i][k];
printf("%d\n",size);
}
}
}