PBDS学习笔记(一)

PBDS学习笔记(一)

pbds简介

平板电视库学习笔记。总结一份偏向acm应用的pbds库笔记。
//首先需要以下头文件以及命名空间
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace __gnu_pbds;

hash

简介

    cc_hash_table<int, bool> h1; //拉链法处理冲突
    gp_hash_table<int, bool> h2; //探测法处理冲突

例题:n个数,m次询问,查询数字是否出现,用法类似map

codevs 1230

#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <bits/stdc++.h>

using namespace __gnu_pbds;
using namespace std;

int main()
{
    cc_hash_table<int, bool> h1; //拉链法处理冲突
    gp_hash_table<int, bool> h2; //探测法处理冲突
    int n, m;
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++ ) {
        int x;
        scanf("%d", &x);
        h1[x] = 1;
    }
    while(m--) {
        int x;
        scanf("%d", &x);
        printf("%s
", h1[x] ? "YES" : "NO");
    }
    return 0;
}

平常用的堆是 c++stl 中的 priority_queue. pbds支持可并堆。

首先需要头文件

#include <ext/pb_ds/priority_queue.hpp>

例题1:FJUTOJ 2109 优先队列的实现(代替priority_queue的一些功能)

#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/priority_queue.hpp>
#include <bits/stdc++.h>

using namespace __gnu_pbds;
using namespace std;

int data, n;

char opt[10];

int main()
{
    __gnu_pbds::priority_queue<int, less<int>, pairing_heap_tag> que;
    while(~scanf("%d ", &n)) {
        que.clear();
        while(!que.empty()) {
            que.pop();
        }
        for(int i = 1; i <= n; i ++ ) {
            scanf("%s", opt);
            if(opt[1] == 'u') {
                scanf("%d", &data);
                que.push(data);
            } else {
                if(que.empty()) {
                    puts("Empty");
                } else {
                    printf("%d
", que.top());
                    que.pop();
                }
            }
        }
    }
    return 0;
}

堆的合并

咕咕咕~~~,代补,今天主要想学平衡树部分。

红黑树

简介

听说可以实现名次树和自定义函数。偷懒的时候代替splay,比赛不能用还能拿来对拍
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <bits/stdc++.h>

using namespace __gnu_pbds;
using namespace std;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> rbtree;

/// int类型
/// null_type为映射类型, 低版本g++为 null_mapped_type
/// less<int>, greater<int> 比较器
/// rb_tree_tag 和 splay_tree_tag 选择树的类型
/// tree_order_statistics_node_update 结点更新

/// insert, erase
/// order_of_key rank
/// find_by_order() kth
/// lower_bound() 前继, >=x 最小的迭代器
/// upper_bound() 后继   >x  最小的迭代器
/// a.join(b) b并入a,前提是两颗树的取值范围不相交
/// a.split(v, b) key <= v的属于a,其他属于
/// 注意,插入的元素会去重,如set

实现一道例题 FJUTOJ 不差钱

#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <bits/stdc++.h>

using namespace __gnu_pbds;
using namespace std;

const int MAXN = 3000000 + 10;

int price, menu[MAXN], cnt[MAXN];

typedef tree<int, null_type, greater<int>, rb_tree_tag, tree_order_statistics_node_update> rbtree;

int n, opt, x;

rbtree tre;

int main()
{
    scanf("%d", &price);
    int id = 1;
    while(~scanf("%d", &opt) && opt) {
        scanf("%d", &x);
        if(opt == 1) { /// add price of x
            tre.insert(x);
            cnt[x]++;       /// 价格x的菜的数量
            menu[id++] = x; /// 第id道菜价格x
            continue;
        }
        if(opt == 2) {
            int p = menu[x];
            if(cnt[p]) {
                cnt[p]--;
            }
            continue;
        }
        if(opt == 3) {
            int res = *tre.find_by_order(x - 1);
            if(res > price) {
                puts("Dui bu qi,Mei you.");
            } else if(cnt[res] == 0) {
                puts("Mei you. Zhe ge ke yi you. Zhe ge zhen mei you!");
            } else {
                printf("You. %d Yuan.
", res);
            }
        }
    }
    return 0;
}

顺便付上正常的splay的解法,有点长,平板电视真好用

#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <bits/stdc++.h>

using namespace __gnu_pbds;
using namespace std;

const int MAXN = 1000000 + 10;

int price, menu[MAXN], cnt[MAXN];

template<class T>
inline bool nextInt(T &n) {
    T x = 0, tmp = 1; char c = getchar();
    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
    if(c == EOF) return false;
    if(c == '-') c = getchar(), tmp = -1;
    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'), c = getchar();
    n = x*tmp; return true;
}

template<class T>
inline void Out(T n) {
    if(n < 0) { putchar('-'); n = -n; }
    int len = 0, data[20];
    while(n) { data[len++] = n%10; n /= 10; }
    if(!len) data[len++] = 0;
    while(len--) putchar(data[len]+48);
}


struct Splay_Tree {

    struct Node {
        int father, childs[2], key, cnt, _size;
        inline void init() {
            father = childs[0] = childs[1] = key = cnt = _size = 0;
        }
        inline void init(int father, int lchild, int rchild, int key, int cnt, int sz) {
            this -> father = father, childs[0] = lchild, childs[1] = rchild;
            this -> key = key, this -> cnt = cnt, _size = sz;
        }
    } tre[MAXN];

    int sign, root;

    inline void init() {
        sign = root = 0;
    }

    inline bool judge(int x) {
        return tre[ tre[x].father ].childs[1] == x;
    }

    inline void update(int x) {
        if(x) {
            tre[x]._size = tre[x].cnt;
            if(tre[x].childs[0]) {
                tre[x]._size += tre[ tre[x].childs[0] ]._size;
            }
            if(tre[x].childs[1]) {
                tre[x]._size += tre[ tre[x].childs[1] ]._size;
            }
        }
    }

    inline void rotate(int x) {
        int y = tre[x].father, z = tre[y].father, k = judge(x);

        //tre[y].childs[k] = tre[x].childs[!k], tre[ tre[x].childs[!k] ].father = y;
        //tre[x].childs[!k] = y, tre[y].father = x;
        //tre[z].childs[ tre[z].childs[1] == y ] = x, tre[x].father = z;

        if(k == 0) { ///zig
            tre[y].childs[0] = tre[x].childs[1], tre[ tre[x].childs[1] ].father = y;
            tre[x].childs[1] = y, tre[y].father = x;
        } else { ///zag
            tre[y].childs[1] = tre[x].childs[0], tre[ tre[x].childs[0] ].father = y;
            tre[x].childs[0] = y, tre[y].father = x;
        }
        tre[z].childs[ tre[z].childs[1] == y ] = x, tre[x].father = z;

        update(y);
    }

    inline void splay(int x,int goal) {
        for(int father; (father = tre[x].father) != goal; rotate(x) ) {
            if(tre[father].father != goal) {
                rotate(judge(x) == judge(father) ? father : x);
            }
        }
        root = x;
    }

    inline void insert_node(int x) {
        if(root == 0) {
            tre[++sign].init(0, 0, 0, x, 1, 1);
            root = sign;
            return ;
        }
        int now = root, father = 0;
        while(1) {
            if(tre[now].key == x) {
                tre[now].cnt ++;
                update(now), update(father);
                splay(now, 0);
                break;
            }
            father = now;
            if(x > tre[now].key) {
                now = tre[now].childs[1];
            } else {
                now = tre[now].childs[0];
            }
            if(now == 0) {
                tre[++sign].init(father, 0, 0, x, 1, 1);
                if(x > tre[father].key) {
                    tre[father].childs[1] = sign;
                } else {
                    tre[father].childs[0] = sign;
                }
                update(father);
                splay(sign, 0);
                break;
            }
        }
    }

    inline int pre() {
        int now = tre[root].childs[0];
        while(tre[now].childs[1]) {
            now = tre[now].childs[1];
        }
        return now;
    }

    inline int next() {
        int now = tre[root].childs[1];
        while(tre[now].childs[0]) {
            now = tre[now].childs[0];
        }
        return now;
    }

    inline int find_rank(int x) { /// 找x的排名
        int now = root, ans = 0;
        while(1) {
            if(x < tre[now].key) {
                now = tre[now].childs[0];
            }
            else {
                if(tre[now].childs[0]) {
                    ans += tre[ tre[now].childs[0] ]._size;
                }
                if(x == tre[now].key) {
                    splay(now, 0);
                    return ans + 1;
                }
                ans += tre[now].cnt;
                now = tre[now].childs[1];
            }
        }
    }

    inline int find_by_order(int x) {
        int now = root;
        while(1) {
            if(tre[now].childs[1] && x <= tre[ tre[now].childs[1] ]._size ) {
                now = tre[now].childs[1];
            } else {
                int rchild = tre[now].childs[1], sum = tre[now].cnt;
                if(rchild) {
                    sum += tre[rchild]._size;
                }
                if(x <= sum) {
                    int ans = tre[now].key;
                    splay(now, 0);
                    return ans;
                }
                x -= sum;
                now = tre[now].childs[0];
            }
        }
    }

    inline int find_rankx(int x) { /// 找排名为x的数字
        int now = root;
        while(1) {
            if(tre[now].childs[0] && x <= tre[ tre[now].childs[0] ]._size ) {
                now = tre[now].childs[0];
            } else {
                int lchild = tre[now].childs[0], sum = tre[now].cnt;
                if(lchild) {
                    sum += tre[lchild]._size;
                }
                if(x <= sum) {
                    return tre[now].key;
                }
                x -= sum;
                now = tre[now].childs[1];
            }
        }
    }

    inline void del(int x) {
        find_rank(x);
        if(tre[root].cnt > 1) {
            tre[root].cnt --;
            update(root);
            return ;
        }
        if(!tre[root].childs[0] && !tre[root].childs[1]) {
            tre[root].init();
            root = 0;
            return ;
        }
        if(!tre[root].childs[0]) {
            int old_root = root;
            root = tre[root].childs[1], tre[root].father = 0, tre[old_root].init();
            return ;
        }
        if(!tre[root].childs[1]) {
            int old_root = root;
            root = tre[root].childs[0], tre[root].father = 0, tre[old_root].init();
            return ;
        }
        int pre_node = pre(), old_root = root;
        splay(pre_node, 0);
        tre[root].childs[1] = tre[old_root].childs[1];
        tre[ tre[old_root].childs[1] ].father = root;
        tre[old_root].init();
        update(root);
    }

    inline bool find(int x) {
        int now = root;
        while(1) {
            if(now == 0) {
                return 0;
            }
            if(x == tre[now].key) {
                splay(now, 0);
                return 1;
            }
            if(x > tre[now].key) {
                now = tre[now].childs[1];
            } else {
                now = tre[now].childs[0];
            }
        }
    }

} tre;

int n, opt, x;

int main()
{
    scanf("%d", &price);
    int id = 1;
    while(nextInt(opt) && opt) {
        //scanf("%d", &x);
        nextInt(x);
        if(opt == 1) { /// add price of x
            tre.insert_node(x);
            cnt[x]++;       /// 价格x的菜的数量
            menu[id++] = x; /// 第id道菜价格x
            continue;
        }
        if(opt == 2) {
            int p = menu[x];
            tre.find(p);
            if(cnt[p]) {
                cnt[p]--;
            }
            continue;
        }
        if(opt == 3) {
            int res = tre.find_by_order(x);
            if(res > price) {
                puts("Dui bu qi,Mei you.");
            } else if(cnt[res] == 0) {
                puts("Mei you. Zhe ge ke yi you. Zhe ge zhen mei you!");
            } else {
                printf("You. %d Yuan.
", res);
            }
        }
    }


    return 0;
}

原文地址:https://www.cnblogs.com/Q1143316492/p/9536364.html