SPLAY(伸展树)
旋转节点至根 (相对位置)
对于一个链的情况 旋转操作 为先转
,再转
对于一个折线的情况 旋转操作 为先转
,再转
切记不能转反 否者 不能保证树的高度为 &preview=true)
左旋和右旋操作
在对的红框的元素进行 左/右 旋 操作 要以其的 右/左 儿子作为轴 进行 操作,被粉红色标记的边为 被影响的边
插入序列 操作

若想 之间 插入 一段序列 ,需要将
旋转至根节点 ,
旋转至
的下方, 此时
的左儿子必定为 空,(因为
为
的后继 若
存在 左儿子则
的后继 必不可能为
) , 所以将 所要插入序列的 插入至
的左儿子即可.
删除序列 操作
同样的若想删除 区间的序列 需要将
的前驱
和
的后继
并将
旋转至 根节点
旋转至
的下方 , 之后只需要将
的左儿子清空即可
上传操作
通过两个儿子节点信息计算出 父节点的信息
下传操作
将父节点的的懒标记 下传给两个儿子
寻找某个节点中序遍历的 后继
x 寻找
节点的后继 若
节点存在右儿子 则 这个后继必定在 右儿子中第一个没有左儿子的节点 若不存在 则 一直向上寻找其祖宗节点 直到找一个节点的父节点 ,这个节点是这个父节点的左儿子 那么这个父节点 就是
的后继
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define NUM 100010
using namespace std;
int n,m;
struct node{
int p,s[2],val;
int flag,size;
void init(int _p,int _val){
p = _p;
val = _val;
size = 1;
}
node(){
size = 0;
flag = 0;
}
}sn[(NUM<<1)];
int root ,idx;
void pushdown(int x){
node &p = sn[x];
if (p.flag){
swap(p.s[0],p.s[1]);
sn[p.s[0]].flag^=1;
sn[p.s[1]].flag^=1;
p.flag = 0;
}
}
void pushup(int x){
node &p = sn[x];
p.size = sn[p.s[0]].size + sn[p.s[1]].size + 1;
}
void rotate(int x){
int y = sn[x].p,z = sn[y].p;
int f = sn[y].s[1] == x; // f = 0 为其父节点,左儿子 ,1 为其父节点的右儿子
sn[z].s[y == sn[z].s[1]] = x; sn[x].p = z;
sn[y].s[f] = sn[x].s[f^1];sn[sn[x].s[f^1]].p = y;
sn[x].s[f^1] = y; sn[y].p = x;
pushup(y),pushup(x);
}
void splay(int x,int k){
while (sn[x].p != k){
int y = sn[x].p,z = sn[y].p;
if (k != z){
if ((sn[y].s[1] == x)^(sn[z].s[1] == y) ) rotate(x);
else rotate(y);
}
rotate(x);
}
if (!k) root = x;
}
void push(int x){
int u = root ,p =0;
while (u){
p = u;
u = sn[u].s[x > sn[u].val];
}
u = ++idx;
if (p) sn[p].s[x>sn[p].val] = u;
sn[u].init(p,x);
splay(u,0);
}
int getk(int x){
int u = root;
while (1){
pushdown(u);
node &p = sn[u];
if (sn[p.s[0]].size>=x) u = p.s[0];
else if (sn[p.s[0]].size+1 == x) return u;
else x-=sn[p.s[0]].size+1, u = p.s[1];
}
return -1;
}
void out(int u){
pushdown(u);
node &p = sn[u];
if (p.s[0]!=0) out(p.s[0]);
if (p.val>=1 && p.val <=n) printf ("%d ",p.val);
if (p.s[1]) out(p.s[1]);
}
int main () {
scanf("%d%d",&n,&m);
for (int i=0;i<=n+1;++i) push(i);
for (int i=0;i<m;i++){
int l,r;
scanf("%d%d",&l,&r);
l = getk(l);r = getk (r+2);
splay(l,0);
splay(r,l);
sn[sn[r].s[0]].flag^=1;
}
out(root);
return 0;
} 






京公网安备 11010502036488号