POJ 1442 Black Box(treap树)

题目链接:点击打开链接

思路:treap树模板题, 可以动态维护一个有序表, 支持在O(logN)的时间内完成插入、删除一个元素和查找第K大元素的任务。 当然, treap树能做到的还远远不止这些, 常常与其他数据结构嵌套。

treap树是一种平衡二叉搜索树, 既满足堆的条件, 又满足排序二叉树的条件。

细节参见代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#include <ctime>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const ld eps = 1e-9, PI = 3.1415926535897932384626433832795;
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 3e4 + 10;
int T,n,m,a[maxn], cc, v;
struct treap {
    int root, treapcnt, key[maxn],priority[maxn],
    childs[maxn][2], cnt[maxn], _size[maxn];
    treap() {
        root = 0;
        treapcnt = 1;
        priority[0] = INF;
        _size[0] = 0;
    }
    void update(int x) {
        _size[x] = _size[childs[x][0]] + cnt[x] + _size[childs[x][1]];
    }
    void _rotate(int &x, int t) {
        int y = childs[x][t]; //为了维持平衡而做的旋转操作,它并不直观
        childs[x][t] = childs[y][1-t];
        childs[y][1-t] = x;
        update(x);
        update(y);
        x = y;
    }
    void _insert(int &x, int k) {
        if(x) { //x == 0 表示该结点为空, 反之非空
            if(key[x] == k) cnt[x]++; //cnt[x]表示结点x的值的个数,key[x]表示结点x的值
            else {
                int t = key[x] < k; //根据排序二叉树规则递归下去
                _insert(childs[x][t], k);
                if(priority[childs[x][t]] < priority[x]) { //根据堆排序规则
                    _rotate(x, t);
                }
            }
        }
        else {
            x = treapcnt++; //创建新的结点
            key[x] = k;
            cnt[x] = 1;
            priority[x] = rand(); //如果优先级是随机的,那么可以证明treap的期望深度是logN
            childs[x][0] = childs[x][1] = 0; //0表示为空
        }
        update(x);
    }
    void _erase(int &x, int k) {
        if(key[x] == k) {
            if(cnt[x] > 1) --cnt[x];
            else {
                if(childs[x][0] == 0 && childs[x][1] == 0) {
                    x = 0; return ; //x设为0表示空
                }
                int t = priority[childs[x][0]] > priority[childs[x][1]];
                _rotate(x, t);  //直到把该结点旋转到叶子再删除
                _erase(x, k);
            }
        }
        else _erase(childs[x][key[x]<k], k);

        update(x);
    }
    int _getKth(int &x, int k) {
        if(k <= _size[childs[x][0]]) return _getKth(childs[x][0], k); //size[x]表示以x为根的子树的值得个数
        k -= _size[childs[x][0]] + cnt[x];  //如果在右边,那么将要找右边的第k-size小的数
        if(k <= 0) return key[x];
        return _getKth(childs[x][1], k);
    }
    void insert(int k) {
        _insert(root, k);
    }
    void erase(int k) {
        _erase(root, k);
    }
    int getKth(int k) {
        return _getKth(root, k);
    }

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

        treap g;
        for(int i = 1; i <= n; i++) {
            scanf("%d",&a[i]);
        }
        cc = 1;
        for(int i = 1; i <= m; i++) {
            scanf("%d",&v);
            while(v >= cc) g.insert(a[cc++]);
            printf("%d\n", g.getKth(i));
        }
    }
    return 0;
}
时间: 2024-07-30 10:19:00

POJ 1442 Black Box(treap树)的相关文章

poj 1442 Black Box (treap树入门题)

1 /**************************************************** 2 题目: Black Box(poj 1442) 3 链接: http://poj.org/problem?id=1442 4 题意: 给n个数,m个询问,对第i数个询问前Xi个数中第 5 i小的是那个数. 6 算法: treap树 7 *****************************************************/ 8 #include<iostream

POJ 1442 Black Box treap求区间第k大

题目来源:POJ 1442 Black Box 题意:输入xi 输出前xi个数的第i大的数 思路:试了下自己的treap模版 #include <cstdio> #include <cstring> #include <cstdlib> #include <ctime> using namespace std; struct Node { Node *ch[2]; int r; int v; int s; Node(){} Node(int v): v(v)

poj 1442 -- Black Box

Black Box Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7183   Accepted: 2920 Description Our Black Box represents a primitive database. It can save an integer array and has a special i variable. At the initial moment Black Box is empt

[ACM] POJ 1442 Black Box (堆,优先队列)

Black Box Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7099   Accepted: 2888 Description Our Black Box represents a primitive database. It can save an integer array and has a special i variable. At the initial moment Black Box is empt

POJ 1442 Black Box(优先队列)

题目地址:POJ 1442 这题是用了两个优先队列,其中一个是较大优先,另一个是较小优先.让较大优先的队列保持k个.每次输出较大优先队列的队头. 每次取出一个数之后,都要先进行判断,如果这个数比较大优先的队列的队头要小,就让它加入这个队列,队列头移到较小优先的队列中.然后当较大优先的数不足k个的时候,就让较小优先的队列的队头移到较大优先的队头中. 代码如下: #include <iostream> #include <cstdio> #include <string>

Treap [POJ 1442] Black Box

Black Box Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7770   Accepted: 3178 Description Our Black Box represents a primitive database. It can save an integer array and has a special i variable. At the initial moment Black Box is empt

POJ 1442 Black Box 基础Treap

高中的时候做过这个,是用两个堆搞的,现在看来其实就是实现一个很简答的数据结构,能够插入元素,找第k大,用平衡树来搞其实是大材小用了,就当做是练习吧. Treap是利用除了键值之外另外一个rand_key域的随机性来保证平衡的,所以说只要随机函数够好,理论上应该是平衡的,而且写起来比较方便. #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include &

Poj 2182-Lost Cows(Treap||树状数组+二分答案)

题目链接:点击打开链接 题意:n个牛编号为1-n 现在编号顺序已经打乱,给出a[i] ,a[i] 代表i位置前面有几个小于它的编号,求编号顺序. 倒着推,对于最后一个a[i] , 最后位置编号肯定是 a[i]+1,然后在1-n个编号中删掉当前编号,继续往前推..即求第 a[i]+1小数,初始容器中有n个数(1-n) ,每求出来一个就删掉.先用平衡树水了一发..明天写树状数组解法. #include <algorithm> #include <iostream> #include &

数据结构(堆):POJ 1442 Black Box

Black Box Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 10658   Accepted: 4390 Description Our Black Box represents a primitive database. It can save an integer array and has a special i variable. At the initial moment Black Box is emp