Treap入门题

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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值