__以前认为平衡树一点也不好理解,可是学了之后发现还可以,就是代码有点多,但是功能真的是很强大, __学习来源
以普通平衡树为例
这个splay最重要的是一个splay, 直接将某个点转到根节点, 如果想进行一些操作, 可以直接在上面操作了,
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10 ;
int f[N] , cnt[N] , ch[N][2] , size[N] , key[N] , sz , rt ;
void clear(int x)
{
f[x] = cnt[x] = ch[x][0] = ch[x][1] = size[x] = key[x] = 0 ;
}
bool get(int x)
{
return ch[f[x]][1] == x ;
}
void pushup(int x)
{
if (x)
{
size[x]=cnt[x];
if (ch[x][0]) size[x]+=size[ch[x][0]];
if (ch[x][1]) size[x]+=size[ch[x][1]];
}
}
void rotate(int x)
{
int old = f[x] , oldf = f[old] , which = get(x) ;
ch[old][which] = ch[x][which ^ 1] ;
f[ch[old][which]] = old ;
ch[x][which ^ 1] = old , f[old] = x ;
f[x] = oldf ;
if(oldf)
ch[oldf][ch[oldf][1] == old] = x ;
pushup(old) , pushup(x) ;
}
void splay(int x)
{
for(int fa ; fa = f[x] ; rotate(x))
if(f[fa])
rotate(get(x) == get(fa) ? fa : x ) ;
rt = x ;
}
void insert(int x)
{
if(rt == 0)
{
sz ++ , key[sz] = x , rt = sz ;
cnt[sz] = size[sz] = 1 ;
f[sz] = ch[sz][1] = ch[sz][0] = 0 ;
return ;
}
int now = rt , fa = 0 ;
while(1)
{
if(x == key[now])
{
cnt[now] ++ , pushup(now) , pushup(fa) , splay(now) ;
return ;
}
fa = now , now = ch[now][key[now] < x] ;
if(now == 0)
{
sz ++ ;
size[sz] = cnt[sz] = 1 ;
ch[sz][0] = ch[sz][1] = 0 ;
ch[fa][x > key[fa]] = sz ;
f[sz] = fa ;
key[sz] = x ;
pushup(fa) ;
splay(sz) ;
return ;
}
}
}
int rnk(int x)
{
int now = rt , ans = 0 ;
while(1)
{
if(x < key[now]) now = ch[now][0] ;
else
{
ans += size[ch[now][0]] ;
if(x == key[now])
{
splay(now) ;
return ans + 1 ;
}
ans += cnt[now] ;
now = ch[now][1] ;
}
}
}
int kth(int x)
{
int now = rt ;
while(1)
{
if(ch[now][0] && x <= size[ch[now][0]])
now = ch[now][0] ;
else
{
int temp = size[ch[now][0]] + cnt[now] ;
if(x <= temp)
return key[now] ;
x -= temp , now = ch[now][1] ;
}
}
}
int pre()
{
int now = ch[rt][0] ;
while(ch[now][1]) now = ch[now][1] ;
return now ;
}
int next()
{
int now = ch[rt][1] ;
while(ch[now][0])
now = ch[now][0] ;
return now ;
}
void del(int x)
{
rnk(x) ;
if(cnt[rt] > 1)
{
cnt[rt] -- , pushup(rt) ;
return ;
}
if(!ch[rt][1] && !ch[rt][0])
{
clear(rt) , rt = 0 ;
return ;
}
if(!ch[rt][0])
{
int oldrt = rt;
rt = ch[rt][1] , f[rt] = 0 , clear(oldrt) ;
return ;
}
else if(!ch[rt][1])
{
int oldrt = rt ; rt = ch[rt][0] ;
f[rt] = 0 , clear(oldrt) ;
return ;
}
int oldrt = rt ;
int leftbig = pre() ;
splay(leftbig) ;
ch[rt][1] = ch[oldrt][1] ;
f[ch[oldrt][1]] = rt ;
clear(oldrt) ;
pushup(rt) ;
}
int main()
{
int n ;
scanf("%d" , &n) ;
for(int i = 1; i <= n ;i ++)
{
int type , k ;
scanf("%d%d" , &type , &k) ;
if(type == 1) insert(k) ;
else if(type == 2) del(k) ;
else if(type == 3) cout << rnk(k) << endl ;
else if(type == 4) cout << kth(k) << endl ;
else if(type == 5) insert(k) , cout << key[pre()] << endl , del(k) ;
else if(type == 6) insert(k) , cout << key[next()] << endl , del(k);
}
}