旋转的规则
一:Zig
此时节点 u 是 root
v 是左孩子:右旋
v 是右孩子:左旋
二:Zig_Zig ( v , u 同侧,先 u 再 v)
此时节点 u 不是 root
v 与 u 同为左孩子: 右旋两次
v 与 u 同为右孩子: 左旋两次
三:Zig_Zag ( v ,u 异侧,先 v 再 u)
此时节点 u 不是 root
v 是左孩子,u 是右孩子:v 先右旋,再左旋
v 是右孩子,u 是左孩子:v 先左旋,再右旋
一、旋转
Splay 的核心操作
struct node{
int fa,id,cnt,size;
int son[2]; // 0 为左儿子, 1 为右儿子
}tree[MAXN];
void updata(int x)
{
int Ls = tree[x].son[0];
int Rs = tree[x].son[1];
tree[x].size = tree[Ls].size + tree[Rs].size + tree[x].cnt;
}
void rotate(int x)
{
int y = tree[x].fa; //fa
int z = tree[y].fa; //grandfa
int k = tree[y].son[1]==x; //left | right son
/**这里很巧妙,笔记一下,用双等于代替 if **/
tree[z].son[tree[z].son[1]==y] = x;
tree[x].fa = z;
tree[y].son[k] = tree[x].son[k^1];
tree[tree[x].son[k^1]].fa = y;
tree[x].son[k^1] = y;
tree[y].fa = x;
}
void Splay(int x, int goal) //将 x 旋转为 goal 的儿子
{
while (tree[x].fa != goal)
{
int y = tree[x].fa;
int z = tree[y].fa;
if (z != goal)
{
(tree[y].son[1]==x) ^ (tree[z].son[1]==y) ? rotate(x) : rotate(y);
}
rotate(x);
}
if (goal == 0)
{
root = x;
}
}
二、普通平衡树
平衡树的基本操作,包括插入节点、删除节点、查找前驱后继、找 k 大(小)值等等。
// find:
// 找到 x 所在的位置,转到 root
/******************************************/
void find(int x)
{
int u = root;
if (!u)
{
return;
}
while (x!=tree[u].id && tree[u].son[x>tree[u].id])
{
u = tree[u].son[x>tree[u].id];
}
Splay(u, 0);
}
//前驱 & 后继
// 先 find
// 前驱为左子树最右点,后继反之
int NEXT(int x, int k) // k 为 0 时找前驱,为 1 时找后继
{
find(x);
int u = root;
if ((tree[u].id>x&&k) || (tree[u].id<x&&!k))
{
return u;
}
u = tree[u].son[k];
while (tree[u].son[k^1])
{
u = tree[u].son[k^1];
}
return u;
}
void insert(int x)
{
int u = root;
int fa = 0;
while (tree[u].id!=x && u)
{
fa = u;
u = tree[u].son[x>tree[u].id];
}
if (u)
{
tree[u].cnt++;
Splay(u, 0);
}
else
{
u = ++tot;
if (fa)
{
tree[fa].son[x>tree[fa].id] = u;
}
tree[u].id = x;
tree[u].fa = fa;
tree[u].son[1] = tree[u].son[0] = 0;
tree[u].cnt = tree[u].size = 1;
Splay(tot, 0);
}
}
void Delete(int x)
{
int last = NEXT(x, 0);
int next = NEXT(x, 1);
Splay(last, 0);
Splay(next, last);
int del = tree[next].son[0];
if (tree[del].cnt > 0)
{
tree[del].cnt--;
Splay(del,0);
}
else
{
tree[next].son[0] = 0;
}
}
int kth(int k)
{
int u = root;
if (tree[u].size < k)
{
return 0;
}
while (1)
{
int Ls = tree[u].son[0];
if(tree[Ls].size+tree[u].cnt < k)
{
k -= (tree[u].cnt+tree[Ls].size);
u = tree[u].son[1];
}
else if(tree[Ls].size >= k)
{
u = Ls;
}
else
{
return tree[u].id;
}
}
}
int Search(int x) // x 的排名
{
find(x);
return tree[tree[root].son[0]].size;
}
int main(void) //虽然不知道为什么,但一定要先 insert 两个最值,不然会 T
{ //这样的话 kth(x+1) 才是答案
insert(-0x7fffffff);
insert( 0x7fffffff);
return 0;
}
三、文艺平衡树
平衡树的区间反转
#include <stdio.h>
#include <iostream>
using namespace std;
#define MAXN 100005
struct node{
int fa, id, tag, size;
int son[2];
}tree[MAXN];
int root, tot;
void down(int x)
{
if (tree[x].tag && x)
{
tree[tree[x].son[0]].tag ^= 1;
tree[tree[x].son[1]].tag ^= 1;
tree[x].tag = 0;
swap(tree[x].son[0], tree[x].son[1]);
}
}
void update(int x)
{
int Ls = tree[x].son[0];
int Rs = tree[x].son[1];
tree[x].size = tree[Ls].size + tree[Rs].size + 1;
}
void rotate(int x)
{
int fa = tree[x].fa;
int grdf = tree[fa].fa;
int k = tree[fa].son[1]==x;
tree[grdf].son[tree[grdf].son[1]==fa] = x;
tree[x].fa = grdf;
tree[fa].son[k] = tree[x].son[k^1];
tree[tree[x].son[k^1]].fa = fa;
tree[x].son[k^1] = fa;
tree[fa].fa = x;
update(fa);
update(x);
}
void Splay(int x, int goal)
{
while (tree[x].fa != goal)
{
int fa = tree[x].fa;
int grdf = tree[fa].fa;
if (grdf != goal)
{
((tree[grdf].son[1] == fa) ^ (tree[fa].son[1] == x)) ? rotate(x) : rotate(fa);
}
rotate(x);
}
if (goal == 0)
{
root = x;
}
}
void Insert(int x)
{
int u = root;
int fa = 0;
while (u)
{
fa = u;
u = tree[u].son[tree[u].id<x];
}
tree[++tot].id = x;
tree[tot].fa = fa;
tree[tot].son[0] = tree[tot].son[1] = 0;
tree[tot].size = 1;
if (fa)
{
tree[fa].son[tree[fa].id<x] = tot;
}
Splay(tot, 0);
}
int kth(int k)
{
int u = root;
while (1)
{
down(u);
if (tree[tree[u].son[0]].size + 1 < k)
{
k -= tree[tree[u].son[0]].size + 1;
u = tree[u].son[1];
}
else if (tree[tree[u].son[0]].size >= k)
{
u = tree[u].son[0];
}
else
{
return u;
}
}
}
void Reverse(int l, int r)
{
int last = kth(l);
int next = kth(r + 2);
Splay(last, 0);
Splay(next, last);
int pos = tree[next].son[0];
tree[pos].tag ^= 1;
}
void Print(int u)
{
down(u);
if (tree[u].son[0])
{
Print(tree[u].son[0]);
}
if (tree[u].id != -0x7fffffff && tree[u].id != 0x7fffffff)
{
cout << tree[u].id << " ";
}
if (tree[u].son[1])
{
Print(tree[u].son[1]);
}
}
int main(void)
{
Insert(-0x7fffffff);
Insert( 0x7fffffff);
int n,m;
cin >> n >> m;
for (int i=1;i<=n;i++)
{
Insert(i);
}
for (int i=1;i<=m;i++)
{
int l,r;
cin >> l >> r;
Reverse(l, r);
}
Print(root);
return 0;
}