题目大意:
有一个长度为n的数列a1-an
支持两个操作:
1 l r 把a[r]放到a[l]的前面a[l]-a[r-1]顺次后移
2 l r k询问a[l]-a[r]中k的个数
n,m<=100000,1<=l,r,k,a[i]<=n
题解:
每个块内记录sum[i]表示i出现的次数,同时维护一个链表,链表中每个元素的下标全局使用,但是每个块内的链表只维护块内元素
换句话说叫“跳表"?同学说的说错了没我事QAQ
然后就是在块内改链表了,各种边界醉了
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=100010;
const int maxb=440;
int a[maxn],n,pos[maxn],cnt=0,m;
int mark1,mark3,mark4;
struct Nodes{int pre,nxt,v;}t[maxn];
struct Block{
int st,fi,sum[maxn],be,ed;
void init(){
be=st; ed=fi;
for (int i=st;i<=fi;++i){
t[i].pre=i-1; t[i].nxt=i+1;
t[i].v=a[i]; sum[a[i]]++;
}
t[be].pre=0; t[ed].nxt=0;
}
}b[maxb];
int read(){
int ret=0;char ch=getchar();
while(ch<'!') ch=getchar();
while(ch>'!') ret=ret*10+ch-'0',ch=getchar();
return ret;
}
void mov1(int l,int r,int L,int R){
if (r==b[R].ed) b[R].ed=t[r].pre;
if (l==b[L].be) b[L].be=r;
t[t[r].pre].nxt=t[r].nxt;
t[t[r].nxt].pre=t[r].pre;
t[r].nxt=l; t[r].pre=t[l].pre;
t[t[l].pre].nxt=r; t[l].pre=r;
}
void mov2(int l,int r,int L,int R){
if (mark1) b[L].be=r;
if (mark3) b[R].be=t[r].nxt;
if (mark4) b[R].ed=t[r].pre;
t[t[r].pre].nxt=t[r].nxt;
t[t[r].nxt].pre=t[r].pre;
t[r].nxt=l; t[r].pre=t[l].pre;
t[t[l].pre].nxt=r; t[l].pre=r;
}
void delw(int id){
int now=b[id].ed,tmp=t[now].pre;
b[id].sum[t[now].v]--;
b[id].ed=tmp; t[tmp].nxt=0;
tmp=b[id+1].be; t[tmp].pre=now;
b[id+1].sum[t[now].v]++;
b[id+1].be=now;
t[now].pre=0; t[now].nxt=tmp;
}
int main(){
n=read();
int blo=sqrt(n); blo=440;
for (int i=1;i<=n;++i) a[i]=read();
for (int i=1;i<=n;++i){
pos[i]=(i-1)/blo+1;
if (pos[i]!=pos[i-1]) b[cnt].fi=i-1,b[++cnt].st=i;
}b[cnt].fi=n;
for (int i=1;i<=cnt;++i) b[i].init();
m=read();
for (int i=1;i<=m;++i){
int opt,x,y,l,r; opt=read();
if (opt==1){
x=read(); y=read();
if (x==y) continue;
int L=pos[x],R=pos[y],num=b[L-1].fi;
for (int j=b[L].be;j;j=t[j].nxt){num++;if(num==x)l=j;}
num=b[R-1].fi;
for (int j=b[R].be;j;j=t[j].nxt){num++;if(num==y)r=j;}
if (L==R) mov1(l,r,L,R);
else{
b[L].sum[t[r].v]++;
b[R].sum[t[r].v]--;
mark1=mark3=mark4=0;
if (l==b[L].be) mark1++;
if (r==b[R].be) mark3++;
if (r==b[R].ed) mark4++;
mov2(l,r,L,R); delw(L);
for (int j=L+1;j<R;++j) delw(j);
}
}else if (opt==2){
int k; x=read(); y=read(); k=read();
int L=pos[x],R=pos[y];
int ans=0;
if (L==R){
int num=b[L-1].fi;
for (int j=b[L].be;j;j=t[j].nxt){
num++;
if (num>=x&&num<=y) ans+=(t[j].v==k);
if (num>y) break;
}
printf("%d\n",ans);
}else{
int num=b[L].fi+1;
for (int i=L+1;i<R;++i) ans+=b[i].sum[k];
for (int j=b[L].ed;j;j=t[j].pre){
ans+=(t[j].v==k);
num--; if(num==x)break;
}
num=b[R-1].fi;
for (int j=b[R].be;j;j=t[j].nxt){
ans+=(t[j].v==k);
num++; if(num==y)break;
}
printf("%d\n",ans);
}
}
}
}