总起
修炼了2天,终于差不多完成基础了,数据结构都是很灵活的,不仅是应用,而且写代码也是有很多值得思考的地方。而在平衡树中,旋转是核心的核心。
先总结一下吧。
先说明一些概念
键值,所谓的key,我一般用val表示,就是当前点存的值。
ind(ex),引索,就是用平衡树要维护的东西,可能还用wei(ght)来表示。相当于普通序列中的下标。
虚拟节点:第n+1个点,放在所有点之前,让平衡树有头;第n+2个点,放在最后,让平衡树有尾。这两个点没有实际意义,用作连接。
siz(e),以当前点为根的子树的点的个数,不包括虚拟点。
cnt,有时候不离散化要来统计相同key的点个数。
root或top,平衡树的根。
Treap
之前感觉splay有点难搞,所以先打一发treap。
treap的核心,就是每一个点的weight。它在保持搜索树同时,要维护weight,保持一个weight的小根堆。其中weight是随机生成的。(随机这种东西要记住啊!!!)
几个操作简介
1,旋转。只有单旋,很朴素,没什么好讲的;
2,插入一个点X。先像普通BST一样插入,然后当X成为了叶节点的时候,一步步把它像栈up上去,保持父亲的weight比儿子的大。
3,删除一个点X。其实有两种。1)把 X down到底下做成叶节点,直接删除,很简洁;2)把X up到顶分裂合并,这个比较麻烦。
4,分裂。即把一棵treap分成左右两边,其中满足BST的性质。这个后面splay再说。
5,合并。其实就是分裂反过来。
6,查找。可以利用size来查。也可以直接用BST的方式查。查找第K大,找元素都很方便。
优点是很明显的:十分容易调,超级简洁。很多都是递归完成,核心也很少。还能可持久化。
缺点:没有吧···
排序的应用代码
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define fo(i,j,k) for(i=j;i<=k;i++)
typedef long long ll;
const int N=2000005,mx=100000007;
const ll pri=1000007,mo=6451342;
//0 left 1 right
int siz[N],tr[N][2],up[N],wei[N],key[N],a[N],n,i,j,cnt[N],top,t1,pos,ans[N];
int pd(int x)
{
return (tr[up[x]][1]==x);
}
void update(int x)
{
siz[x]=siz[tr[x][0]]+siz[tr[x][1]]+cnt[x];
if (siz[39]==30)
{
pos=i;
}
}
void rotate(int x)
{
int y=up[x],z=pd(x);
up[x]=up[y];
if (up[y]) tr[up[y]][pd(y)]=x;
tr[y][z]=tr[x][1-z];
if (tr[x][1-z]) up[tr[x][1-z]]=y;
tr[x][1-z]=y;
up[y]=x;
if (top==y) top=x;
update(y);
update(x);
}
void insert(int x,int y,int z)
{
if (z==key[x])
{
siz[x]++;
cnt[x]++;
return;
}
if (x!=0) siz[x]++;
if (x==0)
{
t1++;
key[t1]=z;
wei[t1]=(ll)(z+100)*pri%mo;
siz[t1]=1;
up[t1]=y;
cnt[t1]++;
int kan=(z<key[y])?0:1;
tr[y][(z<key[y])?0:1]=t1;
return;
}
if (z<key[x])
{
insert(tr[x][0],x,z);
if (wei[tr[x][0]]<wei[x]) rotate(tr[x][0]);
}
else
{
insert(tr[x][1],x,z);
if (wei[tr[x][1]]<wei[x]) rotate(tr[x][1]);
}
}
void dele(int y)
{
int x=top;
while (key[x]!=y)
{
if (y<key[x])
x=tr[x][0];
else
x=tr[x][1];
}
if (cnt[x]==1)
while (tr[x][0]!=0||tr[x][1]!=0)
{
if (wei[tr[x][0]]<wei[tr[x][1]]) rotate(tr[x][0]);
else
rotate(tr[x][1]);
}
y=x;
cnt[x]--;
while (x)
{
update(x);
x=up[x];
}
if (!cnt[y])
{