[Treap] POJ 1442

树堆

通过随机rand选择的priority来平衡二叉树


The nodes of the treap are ordered so that the keys obey the binary-search-tree property and the priorities obey the min-heap order property:


 If v is a left child of u, then v:key < u:key.
 If v is a right child of u, then v:key > u:key.

 If v is a child of u, then v:priority > u:priority.


用Treap实现名次树

名次树支持两个操作:
Kth(x): 找出第k小(第k大)的元素。

Rank(x): 值x的名次,即比x小(大)的结点个数加 1 。

Treap 实现名次树 :  http://www.cnblogs.com/TreeDream/p/6730574.html


#include <iostream>

using namespace std;

const int N = 30005;
int A[ N ];
int u[ N ];

struct Node {
        Node *ch[ 2 ]; //两个孩子
        int pri;       //优先级
        int val;
        int size;

        Node ( int v )
            : val ( v ) {
                ch[ 0 ] = ch[ 1 ] = NULL;
                pri = rand ();
                size = 1;
        }

        bool operator< ( const Node &rhs ) const { return pri < rhs.pri; }

        int cmp ( int x ) const {
                if ( x == val )
                        return -1;
                return x < val ? 0 : 1; //小于去左子树,大于去右子树
        }

        // 记录当前节点有多少个孩子
        void maintain () {
                size = 1;
                if ( ch[ 0 ] != NULL )
                        size += ch[ 0 ]->size;
                if ( ch[ 1 ] != NULL )
                        size += ch[ 1 ]->size;
        }
};

//将左/右孩子旋转到上面,保持树的性质不变
void rotate ( Node *&rt, int d ) {
        Node *sn = rt->ch[ d ^ 1 ];
        rt->ch[ d ^ 1 ] = sn->ch[ d ];
        sn->ch[ d ] = rt;
        rt->maintain ();
        sn->maintain ();
        rt = sn;
}

void insert ( Node *&rt, int x ) {
        if ( rt == NULL )
                rt = new Node ( x );
        else {
                int d = ( x < rt->val ? 0 : 1 );
                insert ( rt->ch[ d ], x );

                if ( rt->ch[ d ]->pri > rt->pri )
                        rotate ( rt, d ^ 1 );
        }

        rt->maintain ();
}

// x是 要删除节点的 val
void remove ( Node *&rt, int x ) {
        int d = rt->cmp ( x );
        Node *u = rt;
        // rt->val 和 x 相等, 找到了节点,开始删除
        if ( d == -1 ) {
                //左右树非空
                if ( rt->ch[ 0 ] != NULL && rt->ch[ 1 ] != NULL ) {
                        int d2 = ( rt->ch[ 0 ]->pri > rt->ch[ 1 ]->pri ? 1 : 0 );
                        rotate ( rt, d2 );
                        remove ( rt->ch[ d2 ], x );
                } else {
                        //左子树空
                        if ( rt->ch[ 0 ] == NULL )
                                rt = rt->ch[ 1 ];
                        //右子树空
                        else
                                rt = rt->ch[ 0 ];
                        delete u;
                }

        } else {
                remove ( rt->ch[ d ], x );
        }

        if ( rt != NULL )
                rt->maintain ();
}

int find ( Node *rt, int x ) {
        while ( rt != NULL ) {
                int d = rt->cmp ( x );
                if ( d == -1 )
                        return 1;
                else
                        rt = rt->ch[ d ];
        }
        return 0;
}

// 第k小的元素 k == size
// 求第k大就把0改成1
int kth ( Node *rt, int k ) {
        if ( rt == NULL || k <= 0 || k > rt->size )
                return -1;
        int s = rt->ch[ 0 ] == NULL ? 0 : rt->ch[ 0 ]->size;
        if ( k == s + 1 )
                return rt->val;
        else if ( k <= s )
                return kth ( rt->ch[ 0 ], k );
        else
                return kth ( rt->ch[ 1 ], k - s - 1 );
}

// 比x小的节点个数+1 x == val
int Rank ( Node *rt, int x ) {
        int tmp;
        if ( rt->ch[ 0 ] == NULL )
                tmp = 0;
        else
                tmp = rt->ch[ 0 ]->size;
        if ( rt->val == x )
                return tmp + 1;
        if ( x < rt->val )
                return Rank ( rt->ch[ 0 ], x );
        else
                return tmp + 1 + Rank ( rt->ch[ 1 ], x );
}

int main () {
        int m, n;
        while ( ~scanf ( "%d%d", &m, &n ) ) {

                Node *rt = NULL;

                for ( int i = 1; i <= m; ++i )
                        scanf ( "%d", &A[ i ] );
                for ( int i = 1; i <= n; ++i )
                        scanf ( "%d", &u[ i ] );

                int cnt = 1;
                int k = 1;

                for ( int i = 1; i <= m; ++i ) {
                        insert ( rt, A[ i ] );
                        while ( u[ cnt ] == i ) {
                                printf ( "%d\n", kth ( rt, k++ ) );
                                ++cnt;
                        }
                }
        }
        return 0;
}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是Treap的代码: ``` #include <bits/stdc++.h> using namespace std; struct Node { int key, priority; Node *left, *right; Node(int key, int priority) : key(key), priority(priority), left(NULL), right(NULL) {} }; struct Treap { Node *root; Treap() : root(NULL) {} void rotateRight(Node *&p) { Node *q = p->left; p->left = q->right; q->right = p; p = q; } void rotateLeft(Node *&p) { Node *q = p->right; p->right = q->left; q->left = p; p = q; } void insert(Node *&p, int key, int priority) { if (p == NULL) { p = new Node(key, priority); return; } if (key < p->key) { insert(p->left, key, priority); if (p->priority < p->left->priority) { rotateRight(p); } } else { insert(p->right, key, priority); if (p->priority < p->right->priority) { rotateLeft(p); } } } void remove(Node *&p, int key) { if (p == NULL) { return; } if (key == p->key) { if (p->left == NULL || p->right == NULL) { Node *q = p; if (p->left == NULL) { p = p->right; } else { p = p->left; } delete q; } else { if (p->left->priority > p->right->priority) { rotateRight(p); remove(p->right, key); } else { rotateLeft(p); remove(p->left, key); } } } else if (key < p->key) { remove(p->left, key); } else { remove(p->right, key); } } bool search(Node *p, int key) { if (p == NULL) { return false; } if (key == p->key) { return true; } if (key < p->key) { return search(p->left, key); } else { return search(p->right, key); } } }; int main() { Treap t; t.insert(t.root, 5, rand()); t.insert(t.root, 3, rand()); t.insert(t.root, 8, rand()); t.insert(t.root, 1, rand()); t.insert(t.root, 4, rand()); t.insert(t.root, 6, rand()); t.insert(t.root, 9, rand());

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值