您的位置:首页 > 其它

Treap入门题

2016-09-21 12:24 375 查看
Treap可以说是最简单的平衡树了,核心是利用随机数,使得二叉排序树的各种操作复杂度平均为O(lgn),写起来也是相当简单。

主要功能有:

Struct Tree{
  int key, size, fa, son[2];
}

void Rotate(int x, int p); //0左旋 1右旋

void Insert(int x,int key) //插入key

void Remove(int x,int key) //删除值为key的节点 若有重点只删其中一个

int getKth(int x,int k) //获得第k大的节点

int getRank(int x,int key) //获得值<=key的节点个数 并将其转移到根处 若<key只需将<=换为<

int getPrev() //返回比根值小的最大值 若无返回0

int getSucc() //返回比根值大的最小值 若无返回0

int getMax(int r) //返回比最大值

int getMin(int r) //返回最小值


模板:

#include <cstdio>
#include <cstdlib>
/*************************Treap模板*****************************/
const int MAXN=1e6+9;
int cnt,rt; //节点编号从1开始
struct Treap {
int key, size, pri, son[2]; //保证父亲的pri大于儿子的pri

} T[MAXN];

int newNode(int key) { //新建结点
++cnt;
T[cnt].key=key;
T[cnt].pri=rand();
T[cnt].size=1;
T[cnt].son[0]=T[cnt].son[1]=0;
return cnt;
}
void Rotate(int &x,int p) { //0左旋 1右旋
int y=T[x].son[!p];
T[x].size=T[x].size-T[y].size+T[T[y].son[p]].size;
T[x].son[!p]=T[y].son[p];
T[y].size=T[y].size-T[T[y].son[p]].size+T[x].size;
T[y].son[p]=x;
x=y;
}

void Insert(int &x,int key) { //插入结点
if(x == 0)x=newNode(key);
else {
T[x].size++;
int p=key < T[x].key;
Insert(T[x].son[!p],key);
if(T[x].pri < T[T[x].son[!p]].pri)
Rotate(x,p);
}
}

void Remove(int &x,int key) { //删除值为key的节点
if(T[x].key == key) {
if(T[x].son[0] && T[x].son[1]) {
int p=T[T[x].son[0]].pri > T[T[x].son[1]].pri;
Rotate(x,p);
Remove(T[x].son[p],key);
} else {
if(!T[x].son[0])
x=T[x].son[1];
else
x=T[x].son[0];
}
} else {
T[x].size--;
int p=T[x].key > key;
Remove(T[x].son[!p],key);
}
}

int getKth(int &x,int p) { //找出第p小的节点的编号
if(p == T[T[x].son[0]].size+1)
return x;
if(p > T[T[x].son[0]].size+1)
return getKth(T[x].son[1],p-T[T[x].son[0]].size-1);
else
return getKth( T[x].son[0],p);
}

int getRank(int &x,int key) { //找出值小于等于key的节点个数
if(x == 0)
return 0;
if(T[x].key <= key)
return T[T[x].son[0]].size+1+getRank(T[x].son[1],key);
else
return getRank( T[x].son[0],key);
}

int getMax(int r) { //得到最大值
while(T[r].son[1])r=T[r].son[1];
return T[r].key;
}
int getMin(int r) { //得到最小值
while(T[r].son[0])r=T[r].son[0];
return T[r].key;
}
int getPrev() { //得到根结点的前驱
int x=T[rt].son[0];
if(!x)return 0;
while(T[x].son[1])x=T[x].son[1];
return x;
}
int getSucc() { //得到根结点的后继
int x=T[rt].son[1];
if(!x)return 0;
while(T[x].son[0])x=T[x].son[0];
return x;
}
/*****************************************************************/


几道简单的入门题:

poj 3481

题目:http://poj.org/problem?id=3481

题意:

主要维护一个优先队列,支持插入,删除,取最大值,取最小值。

分析:

很多解法可做,用Treap的话,支持上述四种操作即可。客户端的名称和优先级用一个map映射一下,然后插入的是优先级。

poj 1442

题目:http://poj.org/problem?id=1442

题意:

黑盒,每次可以ADD一个数,黑盒中数列有序,有一个GET操作,可以查找第k大元素,k从0递增(在每次GET操作后递增)

分析:

很多解法可做,用Treap的话,只有支持插入,查询第k大元素即可。

poj 2352

题目:http://poj.org/problem?id=2352

题意:

y从小到大,若y相同,x从小到大,这样给出一些坐标,求每个点覆盖的点个数,即每个点有左下方的点数。

分析:

相当经典的题目,许多数据结构的入门题。

按照输入顺序插入x,每遇到一个数只需计算小于等于当前元素的数有多少个即可,也就是求Rank。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: