[Treap] poj2761 Feed the dogs

来源:互联网 发布:淘宝关键词怎么来的 编辑:程序博客网 时间:2024/05/22 15:23

题意

给出一个序列,然后给出不同的提问。
提问就是查询在这个序列的某一个区间的第k大

思路

这题按道理来说应该是主席树的模板题,但是在网上看到其实用Treap也可以静态地处理,所以在这里就说说这种Treap的静态处理方法吧。
首先所有的区间都是互不包含的,尽管有可能会相交。
那么可以先按照顺序先排序,然后从左往右往treap中加入元素,然后查询第k大,接着到下一个区间就把多的删掉,没有的加进去。
如此反复,就可静态地求出答案

代码

代码很神奇,加上srand竟然会RE,非常迷
去掉了就AC了……

#include <ctime>#include <cstdio>#include <cstdlib>#include <algorithm>using namespace std;struct Treap {    struct Node {        Node *ch[2];        int r;        int v;        int s;        int cmp(int x) const {            if(x == v) return -1;            return x < v ? 0 : 1;        }        void maintain() {            s = 1;            if(ch[0] != NULL) {                s += ch[0] -> s;            }            if(ch[1] != NULL) {                s += ch[1] -> s;            }        }    } *root;    void init() {        root = NULL;//      srand(time(0));    }    void rotate(Node* &o, int d) {        Node* k = o -> ch[d ^ 1];        o -> ch[d ^ 1] = k -> ch[d];        k -> ch[d] = o;        o -> maintain();        k -> maintain();        o = k;    }    void insert(Node* &o, int x) {        if(o == NULL) {            o = new Node();            o -> ch[0] = o -> ch[1] = NULL;            o -> v = x;            o -> r = rand();        } else {            int d = (x  v ? 0 : 1);            insert(o -> ch[d], x);            if(o -> ch[d] -> r > o -> r) {                rotate(o, d ^ 1);            }        }        o -> maintain();    }    void remove(Node* &o, int x) {        int d = o -> cmp(x);        if(d == -1) {            Node* u = o;            if(o -> ch[0] != NULL && o -> ch[1] != NULL) {                int d2 = (o -> ch[0] -> r > o -> ch[1] -> r ? 1 : 0);                rotate(o, d2);                remove(o -> ch[d2], x);            } else {                if(o -> ch[0] == NULL) {                    o = o -> ch[1];                } else {                    o = o -> ch[0];                }                delete u;            }        } else {            remove(o -> ch[d], x);        }        if(o != NULL) {            o -> maintain();        }    }    int find(Node* o, int x) {        while(o != NULL) {            int d = o -> cmp(x);            if(d == -1) return 1;             else o = o -> ch[d];        }        return 0;    }    int kth(Node* o, int k) {        if(o == NULL || k > o -> s || k <= 0) {            return -1;        }        int s = (o -> ch[0] == NULL ? 0 : o -> ch[0] -> s);        if(k == s + 1) {            return o -> v;        } else {            if(k <= s) {                return kth(o -> ch[0], k);            } else {                return kth(o -> ch[1], k - s - 1);            }        }    }} treap;const int MAXN = 100500,          MAXM = 100500;struct question {    int l, r;    int id;    int k;} q[MAXM];int a[MAXN];bool _cmp(question A, question B) {    return A.l < B.l;}int res[MAXM];int main(void) {    treap.init();    int n, m;    scanf("%d%d", &n, &m);    for(int i = 0; i < n; ++i) {        scanf("%d", &a[i]);    }    for(int i = 0; i < m; ++i) {        int l, r;        scanf("%d%d%d", &q[i].l, &q[i].r, &q[i].k);        q[i].l--;        q[i].r--;        q[i].id = i;    }    sort(q, q + m, _cmp);    int l = 0, r = 0;    for(int i = 0; i < m; ++i) {        for(; l < q[i].l; ++l) {            if(l < r) {                treap.remove(treap.root, a[l]);            }        }        if(r < l) {            r = l;        }        for(; r <= q[i].r; ++r) {            treap.insert(treap.root, a[r]);        }        res[q[i].id] = treap.kth(treap.root, q[i].k);    }    for(int i = 0; i < m; ++i) {        printf("%d\n", res[i]);    }    return 0;}