ZC的序列
题目大意
给一个长度为\(n\)的数列,\(m\)次操作或询问。
每次操作把\([l,r]\)平移\(x\)个单位,每次询问输出\([l,r]\)。
代码及解析
蒟蒻\(TRW\)经过大佬们的愤怒吊锤精心指教之后——
才一个字母一个字母地敲出了这choulou的代码。
这显然是一道平衡树题,可以用\(splay\)维护。
为了方便,我们统一规定向右移动,向左移\(x\iff\)向右移\(-x\)。
每次把\([l,r]\)切下,再插入到第\(l+x-1\)个和第\(l+x\)数之间。
注意,是切下之后的数列的第\(l+x-1\)个和第\(l+x\)数之间。
上代码!
//program from TRW
//splay版本
#include<bits/stdc++.h>
#define b(i) son[i][0]
#define g(i) son[i][1]
#define mid ((l+r)>>1)
#define sex(i) (g(fa[i])==i)
#define up(i) size[i]=size[b(i)]+size[g(i)]+1
using namespace std;
const int nn=101015;
int n,m,opt,l,r,dir,x,a,rt,tot,val[nn];
int fa[nn],size[nn],son[nn][2];
int find(int p,int i){
int st=size[b(p)]+1;
if(i<st)return find(b(p),i);
if(i==st)return p;
return find(g(p),i-st);
}void zg(int p){
int f=fa[p],gf=fa[f];
bool sp=sex(p),sf=sex(f);
int s=son[p][!sp];
fa[f]=p,son[p][!sp]=f;
fa[p]=gf,son[gf][sf]=p;
fa[s]=f,son[f][sp]=s;
up(f),up(p);
}void splay(int a,int b){
int sf=fa[b];
for(;fa[a]!=sf;zg(a))
if(fa[fa[a]]!=sf)
zg(fa[a]);
if(!fa[a])rt=a;
}void plant(int&p,int l,int r){
if(l>r)return ;
p=++tot;
plant(b(p),l,mid-1);
if(mid&&mid<=n)scanf("%d",val+p);
plant(g(p),mid+1,r);
fa[b(p)]=fa[g(p)]=p,up(p);
}void print(int p){
if(!p)return ;
print(b(p));
if(val[p]!=0)printf("%d ",val[p]);
print(g(p));
}int main(){
scanf("%d%d",&n,&m);
for(plant(rt,0,n+1);m--;){
scanf("%d%d%d",&opt,&l,&r);
splay(find(rt,l),rt);
splay(find(rt,r+2),g(rt));
if(opt)print(b(g(rt))),putchar('\n');
else{
a=b(g(rt)),b(g(rt))=0;
up(g(rt)),up(rt);
scanf("%d%d",&dir,&x);
if(!dir)x=-x;
splay(find(rt,l+x),rt);
splay(find(rt,l+x+1),g(rt));
fa[b(g(rt))=a]=g(rt);
up(g(rt)),up(rt);
}
}return 0;
}
//program from TRW
//fhq_treap版本
#include<bits/stdc++.h>
#define up(i) size[i]=size[b(i)]+size[g(i)]+1
#define b(i) son[i][0]
#define g(i) son[i][1]
#define pii pair<int,int>
#define mp make_pair
#define fir first
#define sec second
using namespace std;
const int nn=101015;
int n,m,opt,l,r,dir,x,rt,tot,t1,t2,t3;
int val[nn],rd[nn],size[nn],son[nn][2];
pii f;
void plant(int&p,int l,int r){
if(l>r)return ;
int mid=((l+r)>>1);
rd[p=++tot]=rand();
plant(b(p),l,mid-1);
if(mid&&mid<=n)scanf("%d",val+p);
plant(g(p),mid+1,r),up(p);
}pii cut(int p,int i){
if(!i)return mp(0,p);
pii ans;
int st=size[b(p)]+1;
if(i<st){
ans=cut(b(p),i);
b(p)=ans.second,up(p);
return mp(ans.first,p);
}else{
ans=cut(g(p),i-st);
g(p)=ans.first,up(p);
return mp(p,ans.second);
}
}int merge(int x,int y){
if(!x||!y)return x|y;
if(rd[x]<rd[y])return g(x)=merge(g(x),y),up(x),x;
return b(y)=merge(x,b(y)),up(y),y;
}void print(int p){
if(!p)return ;
print(b(p));
printf("%d ",val[p]);
print(g(p));
}int main(){
srand(time(0));
scanf("%d%d",&n,&m),plant(rt,0,n+1);
while(m--){
scanf("%d%d%d",&opt,&l,&r);
f=cut(rt,l),t1=f.fir,t2=f.sec;
f=cut(t2,r-l+1),t2=f.fir,t3=f.sec;
if(opt)print(t2),putchar('\n');
else{
scanf("%d%d",&dir,&x);
if(!dir)x=-x;
f=cut(merge(t1,t3),l+x);
t1=f.fir,t3=f.sec;
}rt=merge(merge(t1,t2),t3);
}return 0;
}