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
#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\n", 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\n", 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.\n", 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.\n", res);
}
}
}
return 0;
}