平衡树 没有get !
这波,用心的学习一波 Splay (涨姿势了)
旋转规则:
依: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 先左旋,再右旋
接下来放出代码:
struct node{
int fa,w,cnt,size;
int son[2]; // 0 为左儿子, 1 为右儿子
}tree[MAXN];
//旋转:
/******************************************/
void updata(int x)
{
tree[x].size = tree[tree[x].son[0]].size + tree[tree[x].son[1]].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)
{
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;
updata(x); updata(y); //更新子节点数量
}
// find:
// 找到 x 所在的位置,转到 root
/******************************************/
void find(int x)
{
int u = root;
if(!u) return;
while(x!=tree[u].w && tree[u].son[x>tree[u].w])
u = tree[u].son[x>tree[u].w];
Splay(u,0);
}
//前驱 & 后继
// 先 find
// 前驱为左子树最右点,后继反之
/******************************************/
int NEXT(int x, int k) // k 为 0 时找前驱,为 1 时找后继
{
find(x);
int u = root;
if((tree[u].w>x&&k) || (tree[u].w<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,fa = 0;
while(tree[u].w!=x && u)
{
fa = u;
u = tree[u].son[x>tree[u].w];
}
if(u) tree[u].cnt++;
else{
u = ++tot;
if(fa) tree[fa].son[x>tree[fa].w] = u;
tree[u].w = x;
tree[u].fa = fa;
tree[u].son[1] = tree[u].son[0] = 0;
tree[u].cnt = tree[u].size = 1;
}
Splay(u,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].w;
}
}
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;
}