题目描述
小S喜欢有趣的事。但是,每个人的兴趣都是独特的。小S热衷于自问自答。有一天,小S想出了一个问题。
有一个包含n个正整数的数组a和针对这个数组的几个问题。这些问题有两种类型:
1. 在数组下标l到r的部分上,将一个单元格循环移动到右端。即以下面方式重新分配数组上的元素。
a[l], a[l+1], …, a[r-1], a[r] → a[r], a[l], a[l+1], …, a[r-1].
- 在数组下标l到r的部分上,计算有多少元素的值与k相等。
小S很喜欢这个问题并且很快解决了它,你是否能够解决它呢?
分块
因为不太会做所以打暴力!
分块,每块维护循环链表和桶,各种细节敲起来超麻烦……
#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=100000+10,B=320;
int cnt[B+5][maxn],size[B+5],fi[B+5],la[B+5],pre[maxn],next[maxn],a[maxn],belong[maxn],b[maxn];
int i,j,k,l,r,t,n,m,tot,top,ans,now,id,x,ca;
bool czy;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
void work(int x){
int i,t;
fi[x]=t=b[1];
la[x]=b[size[x]];
fo(i,2,size[x]){
next[t]=b[i];
pre[b[i]]=t;
t=b[i];
}
pre[b[1]]=0;
next[b[size[x]]]=0;
}
int main(){
czy=1;
n=read();
fo(i,1,n) a[i]=read();
fo(i,1,n){
belong[i]=(i-1)/B+1;
cnt[belong[i]][a[i]]++;
size[belong[i]]++;
if ((i-1)%B==0) fi[belong[i]]=i;
else{
next[i-1]=i;
pre[i]=i-1;
}
}
top=belong[n];
fo(i,1,n)
if (i==n||i%B==0) la[belong[i]]=i;
m=read();
while (m--){
t=read();
if (t==1){
j=read();k=read();
if (czy){
j=(j+ans-1)%n+1;
k=(k+ans-1)%n+1;
if (j>k) swap(j,k);
}
l=(j-1)/B+1;r=(k-1)/B+1;
if (l==r){
t=fi[l];
fo(i,1,size[l]){
b[i]=t;
t=next[t];
}
j=j-(l-1)*B;k=k-(l-1)*B;
t=b[k];
fd(i,k,j+1) b[i]=b[i-1];
b[j]=t;
work(l);
continue;
}
k=k-(r-1)*B;
t=fi[r];
fo(i,1,size[r]){
b[i]=t;
t=next[t];
}
id=b[k];
fd(i,k,2) b[i]=b[i-1];
b[1]=la[r-1];
cnt[r][a[id]]--;
cnt[r][a[b[1]]]++;
cnt[r-1][a[b[1]]]--;
next[b[1]]=0;
la[r-1]=pre[b[1]];
//pre[b[1]]=0;
work(r);
fd(i,r-1,l+1){
t=la[i-1];
next[t]=fi[i];
pre[fi[i]]=t;
fi[i]=t;
cnt[i][a[t]]++;
cnt[i-1][a[t]]--;
next[pre[t]]=0;
la[i-1]=pre[t];
next[pre[t]]=0;
pre[t]=0;
}
j=j-(l-1)*B;
t=fi[l];
fo(i,1,size[l]-1){
b[i]=t;
t=next[t];
}
fd(i,size[l],j+1) b[i]=b[i-1];
b[j]=id;
cnt[l][a[id]]++;
work(l);
}
else{
ca++;
if (ca==58){
t=t;
}
j=read();k=read();x=read();
if (czy){
j=(j+ans-1)%n+1;
k=(k+ans-1)%n+1;
x=(x+ans-1)%n+1;
if (j>k) swap(j,k);
}
ans=0;
l=(j-1)/B+1;r=(k-1)/B+1;
if (l==r){
t=fi[l];
fo(i,1,size[l]){
b[i]=t;
t=next[t];
}
j=j-(l-1)*B;k=k-(l-1)*B;
fo(i,j,k)
if (a[b[i]]==x) ans++;
printf("%d\n",ans);
continue;
}
fo(i,l+1,r-1) ans+=cnt[i][x];
t=fi[l];
fo(i,1,size[l]){
b[i]=t;
t=next[t];
}
j=j-(l-1)*B;
fo(i,j,size[l])
if (a[b[i]]==x) ans++;
t=fi[r];
fo(i,1,size[r]){
b[i]=t;
t=next[t];
}
k=k-(r-1)*B;
fo(i,1,k)
if (a[b[i]]==x) ans++;
printf("%d\n",ans);
}
}
}