treap模板
2017-09-28 12:42
134 查看
旋转版treap:
//1. 插入x数 //2. 删除x数(若有多个相同的数,因只删除一个) //3. 查询x数的排名(若有多个相同的数,因输出最小的排名) //4. 查询排名为x的数 //5. 求x的前驱(前驱定义为小于x,且最大的数) //6. 求x的后继(后继定义为大于x,且最小的数) const int N = 100000 + 10, INF = 2e9 + 10; struct node { int val, pri, son[2]; int sz, num; void init(int _val, int _pri, int _sz, int _num) { val = _val, pri = _pri, sz = _sz, num = _num; son[0] = son[1] = 0; } }tr ; int tot, root; void init() { tot = 0, root = 0; tr[0].init(0, 0, 0, 0); } void update(int x) { tr[x].sz = tr[tr[x].son[0]].sz + tr[tr[x].son[1]].sz + tr[x].num; } void Rotate(int &x, int p)//p=0左旋,p=1右旋 { int y = tr[x].son[!p]; tr[x].son[!p] = tr[y].son[p]; tr[y].son[p] = x; update(x); update(y);//必须先更新x后更新y x = y; } void Insert(int &x, int val) { if(x == 0) tr[x = ++tot].init(val, rand(), 1, 1); else { tr[x].sz++; if(tr[x].val == val) { tr[x].num++; return; } int p = val > tr[x].val; Insert(tr[x].son[p], val); if(tr[x].pri < tr[tr[x].son[p]].pri) Rotate(x, !p); } } void del(int &x, int val) {//删除之前可以先查看一下这个值是否存在 //if(x == 0) return; if(tr[x].val == val) { if(tr[x].num > 1) { tr[x].sz--; tr[x].num--; return; } if(tr[x].son[0] && tr[x].son[1]) { int p = tr[tr[x].son[0]].pri > tr[tr[x].son[1]].pri; Rotate(x, p); tr[x].sz--;//如果接下删除tr[x].son[p],注意处理tr[x].sz,因为这个一直TLE del(tr[x].son[p], val); //del(x, val); //注释掉的写法不用处理sz的问题,因为递归到下一层会处理 } else { //x = tr[x].son[0] + tr[x].son[1]; //合并,很凝炼 if(tr[x].son[0] != 0) x = tr[x].son[0]; else x = tr[x].son[1]; } } else { int p = val > tr[x].val; tr[x].sz--; del(tr[x].son[p], val); } } int get_kth(int x, int k) { //if(x == 0) return 0; if(k > tr[tr[x].son[0]].sz + tr[x].num) return get_kth(tr[x].son[1], k - tr[tr[x].son[0]].sz - tr[x].num); else if(k <= tr[tr[x].son[0]].sz) return get_kth(tr[x].son[0], k); else return tr[x].val; } int get_rank(int x, int val) { //if(x == 0) return 0; if(val == tr[x].val) return tr[tr[x].son[0]].sz + 1; else if(val > tr[x].val) return get_rank(tr[x].son[1], val) + tr[tr[x].son[0]].sz + tr[x].num; else return get_rank(tr[x].son[0], val); } //求前驱和后继用两种不同的方法,其实一种即可 int get_prec(int x, int val) { int ans = -INF; while(x) { if(val <= tr[x].val) x = tr[x].son[0]; else ans = max(ans, tr[x].val), x = tr[x].son[1]; } return ans; } int get_succ(int x, int val) { if(! x) return INF; if(val >= tr[x].val) return get_succ(tr[x].son[1], val); else return min(tr[x].val, get_succ(tr[x].son[0], val)); } int main() { int n, op, val; scanf("%d", &n); init(); for(int i = 1; i <= n; i++) { scanf("%d%d", &op, &val); if(op == 1) Insert(root, val); else if(op == 2) del(root, val); else if(op == 3) printf("%d\n", get_rank(root, val)); else if(op == 4) printf("%d\n", get_kth(root, val)); else if(op == 5) printf("%d\n", get_prec(root, val)); else if(op == 6) printf("%d\n", get_succ(root, val)); } return 0; }
非旋转版treap
typedef pair<int, int> proot; const int N = 100000 + 10, INF = 2e9 + 10; struct node { int l, r, val, pri, sz; void init(int _val, int _pri, int _sz) { val = _val, pri = _pri, sz = _sz; l = r = 0; } }tr ; int root, tot; void init() { root = 0, tot = 0; tr[0].init(0, 0, 0); } int new_node(int val) { tr[++tot].init(val, rand(), 1); return tot; } void update(int x) { tr[x].sz = 1 + tr[tr[x].l].sz + tr[tr[x].r].sz; } proot split(int x, int k)//把树x分裂成两个树,前k个元素一个数,剩余的元素一个树 { if(! k) return proot(0, x); proot y; if(tr[tr[x].l].sz >= k) { y = split(tr[x].l, k); tr[x].l = y.second; update(x); y.second = x; } else { y = split(tr[x].r, k - tr[tr[x].l].sz - 1); tr[x].r = y.first; update(x); y.first = x; } return y; } int Merge(int x, int y)//把树x,y合并成一棵,并返回树根 { if(!x || !y) return x + y; if(tr[x].pri < tr[y].pri) { tr[x].r = Merge(tr[x].r, y); update(x); return x; } else { tr[y].l = Merge(x, tr[y].l); update(y); return y; } } bool Find(int x, int val) { if(!x) return false; if(val == tr[x].val) return true; else if(val < tr[x].val) return Find(tr[x].l, val); else return Find(tr[x].r, val); } //int get_rank(int x, int val)//树中无重复值才能用这个 //{ // if(!x) return 0; // if(val == tr[x].val) return tr[tr[x].l].sz + 1; // else if(val < tr[x].val) return get_rank(tr[x].l, val); // else return tr[tr[x].l].sz + 1 + get_rank(tr[x].r, val); //} int get_rank(int x, int val)//排名为get_rank()+1 { if(!x) return 0; return val <= tr[x].val ? get_rank(tr[x].l, val) : get_rank(tr[x].r, val) + tr[tr[x].l].sz + 1; } int get_kth(int x, int k) { if(tr[tr[x].l].sz + 1 == k) return tr[x].val; else if(k <= tr[tr[x].l].sz) return get_kth(tr[x].l, k); else return get_kth(tr[x].r, k - tr[tr[x].l].sz - 1); } void Insert(int val) {//插入元素。首先确定新元素的排名,然后依据这个排名把树分裂成两个,然后把新元素夹在两个树中间,合并 int k = get_rank(root, val); proot x = split(root, k); int y = new_node(val); root = Merge(Merge(x.first, y), x.second); } void del(int val) {//删除元素。首先确定元素排名k,然后前k-1个分裂成一个树,剩余的元素再进行一次分裂,把第一个也就是待删除元素单独分裂出来,然后合并即可 int k = get_rank(root, val) + 1; proot x = split(root, k-1); proot y = split(x.second, 1); root = Merge(x.first, y.second); } //int get_prec(int x, int val) //{ // int ans = -INF; // while(x) // { // if(val <= tr[x].val) x = tr[x].l; // else ans = max(ans, tr[x].val), x = tr[x].r; // } // return ans; //} //int get_succ(int x, int val) //{ // if(! x) return INF; // if(val >= tr[x].val) return get_succ(tr[x].r, val); // else return min(tr[x].val, get_succ(tr[x].l, val)); //} int get_prec(int root, int val) { int k = get_rank(root, val); proot x = split(root, k-1); proot y = split(x.second, 1); int ans = tr[y.first].val; root = Merge(Merge(x.first, y.first), y.second); return ans; } int get_succ(int root, int val) { int k = get_rank(root, val+1); proot x = split(root, k); proot y = split(x.second, 1); int ans = tr[y.first].val; root = Merge(Merge(x.first, y.first), y.second); return ans; } int main() { int n, op, val; scanf("%d", &n); init(); for(int i = 1; i <= n; i++) { scanf("%d%d", &op, &val); if(op == 1) Insert(val); else if(op == 2) del(val); else if(op == 3) printf("%d\n", get_rank(root, val) + 1); else if(op == 4) printf("%d\n", get_kth(root, val)); else if(op == 5) printf("%d\n", get_prec(root, val)); else if(op == 6) printf("%d\n", get_succ(root, val)); } return 0; }
相关文章推荐
- P3369 【模板】普通平衡树 Treap
- 算法模板——平衡树Treap
- 【模板】【Treap/SBT】【树堆】普通平衡树【洛谷P3369】
- 平衡树初阶——AVL平衡二叉查找树+三大平衡树(Treap + Splay + SBT)模板【超详解】
- 洛谷P3369 【模板】普通平衡树(Treap/SBT)
- 洛谷 P3369 【模板】普通平衡树(Treap/SBT)
- Black Box+POJ+treap树模板
- 替罪羊树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)
- 【模板】可持久化平衡树(非旋Treap)
- Treap=Tree+Heap! 各种BST大PK(模板)
- [模板] fhqTreap (非旋Treap)+ 可持久化平衡树
- 模板——Treap实现名次树
- poj 3481 treap树堆模板
- BZOJ 3224 TYVJ 1728 普通平衡树 [Treap树模板]
- BZOJ3224:普通平衡树(含SBT、Treap、Splay模板)
- fhq treap最终模板
- 数组splay ------ luogu P3369 【模板】普通平衡树(Treap/SBT)
- uva12538 Version Controlled IDE(可持续化Treap * 模板, STL ext/rope(块状链表))
- treap 排序二叉树的模板
- TREAP 模板(新)