[Treap] POJ 1442

来源:互联网 发布:手机淘宝怎么保存视频 编辑:程序博客网 时间:2024/06/13 21:20

树堆

通过随机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是 要删除节点的 valvoid 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改成1int 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 == valint 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;}



原创粉丝点击