HDU 3487 Play with Chain 【Splay】

1-n的序列,有两种操作:

1,将一段区间翻转

2,将一段区间切下来放到剩余序列的第C个数后

采用延迟更新的方法维护区间的翻转,并维护一个size域。

添加一个最大点和一个最小点,防止出界

翻转时,将第L-1个点伸展到跟,再将第R+1个点伸展到L-1的右子树,这时R+1的左子树就是要翻转的区间,加上一个标记。

切区间时,跟翻转操作差不多,只是不加标记。然后找到C+1和C,将C伸展到根,C+1伸展到C的右子树,此时C+1的左子树就是要插入的位置。

其实我说了这么多并没有什么卵用。。。。最后还是得自己画图看才能懂。

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
const int N=3e5+;
int data[N],num[N],t[N][],id,fa[N];
int flip[N],root,f;
inline void pushup(int x){
num[x]=num[t[x][]]+num[t[x][]]+;
}
inline void pushdown(int x){
if(flip[x]){
flip[x]=;
flip[t[x][]]^=;
flip[t[x][]]^=;
swap(t[x][],t[x][]);
}
}
inline void Rotate(int x,int w){
int y=fa[x];
int z=fa[y];
pushdown(y);
t[y][!w]=t[x][w];
fa[t[x][w]]=y;
t[z][t[z][]==y]=x;
fa[x]=z;
t[x][w]=y;
fa[y]=x;
pushup(y);
}
void newnode(int &x,int y,int v){
x=++id;
t[x][]=t[x][]=;
fa[x]=y;
data[x]=v,flip[x]=;
num[x]=;
}
void build(int &x,int y,int l,int r){
if(l<=r){
int mid=(l+r)>>;
newnode(x,y,mid);
build(t[x][],x,l,mid-);
build(t[x][],x,mid+,r);
pushup(x);
}
}
void init(int n){
f=id=root=;
t[][]=t[][]=num[]=data[]=flip[]=fa[]=;
newnode(root,,-);
newnode(t[][],root,-);
build(t[t[][]][],t[][],,n);
pushup(t[][]);
pushup();
}
void Splay(int x,int y){
if(x!=y){
pushdown(x);
while(fa[x]!=y){
if(t[fa[x]][]==x)
Rotate(x,);
else
Rotate(x,);
}
pushup(x);
if(!y)root=x;
}
}
int Kth(int k){
int x=root;
pushdown(root);
for(;num[t[x][]]+!=k;){
if(num[t[x][]]+>k)
x=t[x][];
else
k-=num[t[x][]]+,x=t[x][];
pushdown(x);
}
return x;
}
void Flip(int a,int b){
a=Kth(a);
b=Kth(b+);
Splay(a,);
Splay(b,a);
flip[t[b][]]^=;
}
void Cut(int a,int b,int c){
int tmp,d; a=Kth(a);b=Kth(b+);
Splay(a,);Splay(b,a);
tmp=t[b][];t[b][]=;
pushup(b);pushup(a); d=Kth(c+);c=Kth(c+);
Splay(c,);Splay(d,c);
t[d][]=tmp;fa[tmp]=d;
pushup(d);pushup(c);
}
void Inorder(int x){
if(x){
pushdown(x);
Inorder(t[x][]);
if(data[x]>){
if(f)
putchar(' ');
else f=;
printf("%d",data[x]);
}
Inorder(t[x][]);
}
}
int main(){
int n,m;
char op[];
while(scanf("%d%d",&n,&m)!=EOF){
if(n==-)break;
init(n);
int a,b,c;
while(m--){
scanf("%s",op);
if(op[]=='F'){
scanf("%d%d",&a,&b);
Flip(a,b);
}else{
scanf("%d%d%d",&a,&b,&c);
Cut(a,b,c);
}
}
Inorder(root);
puts("");
}
return ;
}
上一篇:Linux(五)__硬盘分区


下一篇:mysql插入中文乱码