Treap 模板 poj1442&hdu4557
原理可以看hihocoder上面的讲解,很清楚,不多说了。
模板抄lrj训练指南上面的。
- /**
- Treap 实现 名次树
- 功能: 1.找到排名为k的元素
- 2.值为x的元素的名次
- 初始化:Node* root = NULL;
- */
- #include <cstdlib>
- #include <cstdio>
- #include <cstring>
- #include <vector>
- using namespace std;
- struct Node {
- Node * ch[]; // 0左子树 1右子树
- int r; // 随机优先级
- int v; // 值
- int s; // 以s为根的子树的大小
- Node(int v):v(v)
- {
- ch[] = ch[] = NULL;
- r = rand();
- s = ;
- }
- bool operator<(const Node& rhs) const { // 按随机优先级排序
- return r < rhs.r;
- }
- int cmp(int x) const
- {
- if (x == v) return -;
- return x < v ? : ;
- }
- void maintain() // 更新
- {
- s = ;
- if (ch[] != NULL) s += ch[]->s;
- if (ch[] != NULL) s += ch[]->s;
- }
- } ;
- void rotate(Node* &o, int d) // d=0 代表左转, d=1代表右转
- {
- Node* k = o->ch[d^];
- o->ch[d^] = k->ch[d];
- k->ch[d] = o;
- o->maintain();
- k->maintain();
- o = k;
- }
- void insert(Node* &o, int x) // o是根 x是插入的值
- {
- if (o == NULL) {
- o = new Node(x);
- } else {
- int d = (x < o->v ? : ); // 不用cmp函数因为可能有重复的值
- insert(o->ch[d], x);
- if ((o->ch[d]->r) > (o->r)) rotate(o, d^);
- }
- o->maintain();
- }
- void remove(Node* &o, int x)
- {
- int d = o->cmp(x);
- if (d == -) {
- Node* u = o;
- if (o->ch[] != NULL && o->ch[] != NULL) {
- int d2 = ((o->ch[]->r) > (o->ch[]->r) ? : );
- rotate(o, d2);
- remove(o->ch[d2], x);
- } else {
- if (o->ch[] == NULL) o = o->ch[];
- else o = o->ch[];
- delete u;
- }
- } else {
- remove(o->ch[d], x);
- }
- if (o != NULL) o->maintain();
- }
- int find(Node* o, int x) // 因为remove和insert都没有查值存不存在 记得操作之前调用find
- {
- while (o != NULL) {
- int d = o->cmp(x);
- if (d == -) return ;
- else o = o->ch[d];
- }
- return ;
- }
- int kth(Node* &o, int k, int fg) // fg=1第k大的值 fg=0第k小的值 返回0表示没找到
- {
- if (o == NULL || k <= || k > o->s) return ;
- int s = (o->ch[fg] == NULL ? : o->ch[fg]->s);
- if (k == s+) return o->v;
- else if (k <= s) return kth(o->ch[fg], k, fg);
- else return kth(o->ch[fg^], k-s-, fg);
- }
- int prv(Node* &o, int x) // 查找x前面的元素 (<x的最大值
- {
- if (o == NULL) return -;
- if (x <= o->v) return prv(o->ch[], x);
- int ans = prv(o->ch[], x);
- return ans == - ? o->v : ans;
- }
- int nxt(Node* &o, int x) // 查找x后面的元素 (>x的最大值
- {
- if (o == NULL) return -;
- if (x >= o->v) return nxt(o->ch[], x);
- int ans = nxt(o->ch[], x);
- return ans == - ? o->v : ans;
- }
- void mergeto(Node* &src, Node* &dest) // 合并两棵树 把src加到dest上 src和dest都是树的根
- {
- if (src->ch[] != NULL) mergeto(src->ch[], dest);
- if (src->ch[] != NULL) mergeto(src->ch[], dest);
- insert(dest, src->v);
- delete src;
- src = NULL;
- }
- void print(Node* &o)
- {
- if (o == NULL) return ;
- print(o->ch[]);
- printf("%d ", o->v);
- print(o->ch[]);
- }
- int main()
- {
- Node* root = NULL;
- insert(root, );
- insert(root, );
- insert(root, );
- insert(root, );
- remove(root, );
- print(root);
- return ;
- }
例题:
上面hihocoder的例题,这个代码是照着讲解自己写的
- //Treap.cpp
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- const int N = ;
- struct Treap {
- int father, left, right;
- int key, weight;
- void init(int k, int w, int fa) {
- left = right = -;
- father = fa, key = k, weight = w;
- }
- } tp[N];
- int root;
- int treap_cnt;
- int new_treap(int k, int w, int fa = -)
- {
- tp[treap_cnt].init(k, w, fa);
- return treap_cnt++;
- }
- void left_rotate(int a) // 左旋 把节点A的右儿子节点B转到A的父亲节点
- {
- int b = tp[a].right;
- tp[b].father = tp[a].father;
- if (tp[tp[a].father].left == a) { // 判断a是父节点的左儿子还是右儿子 并用b替换
- tp[tp[a].father].left = b;
- } else {
- tp[tp[a].father].right = b;
- }
- tp[a].right = tp[b].left;
- if (tp[b].left != -) tp[tp[b].left].father = a;
- tp[b].left = a;
- tp[a].father = b;
- }
- void right_rotate(int a) // 右旋 把节点A的左儿子节点B转到A的父亲节点
- {
- int b = tp[a].left;
- tp[b].father = tp[a].father;
- if (tp[tp[a].father].left == a) tp[tp[a].father].left = b;
- else tp[tp[a].father].right = b;
- tp[a].left = tp[b].right;
- if (tp[b].right != -) tp[tp[b].right].father = a;
- tp[b].right = a;
- tp[a].father = b;
- }
- int insert(int a, int key)
- {
- if (key < tp[a].key) {
- if (tp[a].left == -) {
- tp[a].left = new_treap(key, rand(), a);
- return tp[a].left;
- } else {
- return insert(tp[a].left, key);
- }
- } else {
- if (tp[a].right == -) {
- tp[a].right = new_treap(key, rand(), a);
- return tp[a].right;
- } else {
- return insert(tp[a].right, key);
- }
- }
- }
- void rotate(int a) // 维持小顶堆
- {
- int fa = tp[a].father;
- while (fa != -) {
- if (tp[a].weight < tp[fa].weight) {
- if (a == tp[fa].left) right_rotate(fa);
- else left_rotate(fa);
- fa = tp[a].father;
- } else {
- break;
- }
- }
- if (fa == -) root = a;
- }
- int find(int a, int key)
- {
- int cur = a, pre = -;
- while (cur != -) {
- if (tp[cur].key > key) {
- pre = cur;
- cur = tp[cur].left;
- } else if (tp[cur].key < key) {
- pre = cur;
- cur = tp[cur].right;
- } else {
- return key;
- }
- }
- while (pre != -) {
- if (tp[pre].key < key) return tp[pre].key;
- pre = tp[pre].father;
- }
- return -;
- }
- void print(int a)
- {
- if (a == -) return;
- print(tp[a].left);
- printf("%d(%d) ", a, tp[a].key);
- print(tp[a].right);
- }
- int main(int argc, char const *argv[])
- {
- //freopen("in", "r", stdin);
- root = -;
- treap_cnt = ;
- int n;
- char op[];
- int k;
- scanf("%d", &n);
- while (n--) {
- scanf("%s%d", op, &k);
- if (*op == 'I') {
- if (root == -) root = new_treap(k, rand());
- else rotate(insert(root, k));
- } else {
- printf("%d\n", find(root, k));
- }
- }
- return ;
- }
poj1442,直接套模板,比较简单
- /**
- Treap 实现 名次树
- 功能: 1.找到排名为k的元素
- 2.值为x的元素的名次
- */
- #include <cstdlib>
- #include <cstdio>
- #include <cstring>
- #include <vector>
- using namespace std;
- struct Node {
- Node * ch[]; // 0左子树 1右子树
- int r; // 随机优先级
- int v; // 值
- int s; // 以s为根的子树的大小
- Node(int v):v(v)
- {
- ch[] = ch[] = NULL;
- r = rand();
- s = ;
- }
- bool operator<(const Node& rhs) const { // 按随机优先级排序
- return r < rhs.r;
- }
- int cmp(int x) const
- {
- if (x == v) return -;
- return x < v ? : ;
- }
- void maintain() // 更新
- {
- s = ;
- if (ch[] != NULL) s += ch[]->s;
- if (ch[] != NULL) s += ch[]->s;
- }
- } ;
- void rotate(Node* &o, int d) // d=0 代表左转, d=1代表右转
- {
- Node* k = o->ch[d^];
- o->ch[d^] = k->ch[d];
- k->ch[d] = o;
- o->maintain();
- k->maintain();
- o = k;
- }
- void insert(Node* &o, int x) // o是根 x是插入的值
- {
- if (o == NULL) {
- o = new Node(x);
- } else {
- int d = (x < o->v ? : ); // 不用cmp函数因为可能有重复的值
- insert(o->ch[d], x);
- if ((o->ch[d]->r) > (o->r)) rotate(o, d^);
- }
- o->maintain();
- }
- void remove(Node* &o, int x)
- {
- int d = o->cmp(x);
- if (d == -) {
- Node* u = o;
- if (o->ch[] != NULL && o->ch[] != NULL) {
- int d2 = ((o->ch[]->r) > (o->ch[]->r) ? : );
- rotate(o, d2);
- remove(o->ch[d2], x);
- } else {
- if (o->ch[] == NULL) o = o->ch[];
- else o = o->ch[];
- delete u;
- }
- } else {
- remove(o->ch[d], x);
- }
- if (o != NULL) o->maintain();
- }
- int find(Node* &o, int x) // 因为remove和insert都没有查值存不存在 记得操作之前调用find
- {
- while (o != NULL) {
- int d = o->cmp(x);
- if (d == -) return ; // exist
- else o = o->ch[d];
- }
- return ; // not exist
- }
- int kth(Node* &o, int k, int fg) // fg=1第k大的值 fg=0第k小的值 返回0表示没找到
- {
- if (o == NULL || k <= || k > o->s) return ;
- int s = (o->ch[fg] == NULL ? : o->ch[fg]->s);
- if (k == s+) return o->v;
- else if (k <= s) return kth(o->ch[fg], k, fg);
- else return kth(o->ch[fg^], k-s-, fg);
- }
- void mergeto(Node* &src, Node* &dest)
- {
- if (src->ch[] != NULL) mergeto(src->ch[], dest);
- if (src->ch[] != NULL) mergeto(src->ch[], dest);
- insert(dest, src->v);
- delete src;
- src = NULL;
- }
- const int N = ;
- int a[N];
- int main()
- {
- //freopen("in", "r", stdin);
- int m, n;
- while (~scanf("%d%d", &m, &n)) {
- Node* root = NULL;
- for (int i = ; i <= m; ++i) {
- scanf("%d", a+i);
- }
- int x = , u, cnt = ;
- for (int i = ; i < n; ++i) {
- scanf("%d", &u);
- while (cnt < u) {
- insert(root, a[++cnt]);
- }
- printf("%d\n", kth(root, ++x, ));
- }
- }
- return ;
- }
hdu4557
每个结点加了一个元素t,排序查找都要考虑t
- #include <iostream>
- #include <cstdlib>
- #include <cstdio>
- #include <cstring>
- #include <map>
- #include <vector>
- using namespace std;
- struct Node {
- Node * ch[]; // 0左子树 1右子树
- int r; // 随机优先级
- int v; // 值
- int t;
- int s; // 以s为根的子树的大小
- Node(int v, int t):v(v), t(t)
- {
- ch[] = ch[] = NULL;
- r = rand();
- s = ;
- }
- bool operator<(const Node& rhs) const { // 按随机优先级排序
- if (r == rhs.r) return t < rhs.t;
- return r < rhs.r;
- }
- int cmp(int x, int y) const
- {
- if (x == v && y == t) return -;
- if (x == v) return y < t ? : ;
- return x < v ? : ;
- }
- void maintain() // 更新
- {
- s = ;
- if (ch[] != NULL) s += ch[]->s;
- if (ch[] != NULL) s += ch[]->s;
- }
- } ;
- void rotate(Node* &o, int d) // d=0 代表左转, d=1代表右转
- {
- Node* k = o->ch[d^];
- o->ch[d^] = k->ch[d];
- k->ch[d] = o;
- o->maintain();
- k->maintain();
- o = k;
- }
- void insert(Node* &o, int x, int y) // o是根 x是插入的值
- {
- if (o == NULL) {
- o = new Node(x, y);
- } else {
- int d = o->cmp(x, y);
- insert(o->ch[d], x, y);
- if ((o->ch[d]->r) > (o->r)) rotate(o, d^);
- }
- o->maintain();
- }
- void remove(Node* &o, int x, int y)
- {
- int d = o->cmp(x, y);
- if (d == -) {
- Node* u = o;
- if (o->ch[] != NULL && o->ch[] != NULL) {
- int d2 = ((o->ch[]->r) > (o->ch[]->r) ? : );
- rotate(o, d2);
- remove(o->ch[d2], x, y);
- } else {
- if (o->ch[] == NULL) o = o->ch[];
- else o = o->ch[];
- delete u;
- }
- } else {
- remove(o->ch[d], x, y);
- }
- if (o != NULL) o->maintain();
- }
- int nxt(Node* &o, int x, int &res) // 查找x后面的元素 (>=x的最小值
- {
- if (o == NULL) return -;
- if (o->v < x) return nxt(o->ch[], x, res);
- res = o->v;
- int ans = nxt(o->ch[], x, res);
- return ans == - ? o->t : ans;
- }
- void print(Node* &o)
- {
- if (o == NULL) return ;
- print(o->ch[]);
- printf("%d ", o->v);
- print(o->ch[]);
- }
- int main()
- {
- freopen("in", "r", stdin);
- int T;
- cin >> T;
- int cas = ;
- while (T--) {
- printf("Case #%d:\n", ++cas);
- int n;
- cin >> n;
- char op[];
- string name;
- int abi, res;
- Node* root = NULL;
- map<int, string> mp;
- for (int i = ; i < n; ++i) {
- scanf("%s", op);
- if (*op == 'A') {
- cin >> name;
- scanf("%d", &abi);
- mp[i] = name;
- insert(root, abi, i);
- printf("%d\n", root->s);
- } else {
- scanf("%d", &abi);
- int ans = nxt(root, abi, res);
- if (ans == -) printf("WAIT...\n");
- else {
- cout << mp[ans] << endl;
- remove(root, res, ans);
- }
- }//printf("debug:"); print(root); printf("\n");
- }
- }
- }
Treap 模板 poj1442&hdu4557的更多相关文章
- BZOJ 1588: Treap 模板
1588: [HNOI2002]营业额统计 Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 12171 Solved: 4352 Description ...
- [luogu3369]普通平衡树(treap模板)
解题关键:treap模板保存. #include<cstdio> #include<cstring> #include<algorithm> #include< ...
- 平衡树Treap模板与原理
这次我们来讲一讲Treap(splay以后再更) 平衡树是一种排序二叉树(或二叉搜索树),所以排序二叉树可以迅速地判断两个值的大小,当然操作肯定不止那么多(不然我们还学什么). 而平衡树在排序二叉树的 ...
- POJ1442-查询第K大-Treap模板题
模板题,以后要学splay,大概看一下treap就好了. #include <cstdio> #include <algorithm> #include <cstring ...
- Treap 模板
感觉平衡树也没有以前想的那么玄乎,(其实set超好用的),非旋式Treap挺好理解,和可并堆,二叉搜索树有很大联系 推荐博客:http://memphis.is-programmer.com/post ...
- 【Treap模板详细注释】BZOJ3224-普通平衡树
模板题:D错因见注释 #include<iostream> #include<cstdio> #include<cstring> #include<algor ...
- 非旋treap模板
bzoj3580 非旋转treap 在大神教导下发现split一段区间时先split右边再split左边比较好写 #include <cstdio> #include <cstdli ...
- codevs 4543 treap 模板
type rec=record lc,rc,v,rnd,size,w,fa:longint; end; var n,root,tot,ans,opt,x,i,po:longint; tr:array[ ...
- Treap模板
平衡树总是有用的,set由于过度封装没有办法实现找比x小的元素有多少个,这就显得很不方便了,所以封装了个Treap,万一以后用的着呢- -01 #pragma warning(disable:4996 ...
随机推荐
- python time模块详解
python time模块详解 转自:http://blog.csdn.net/kiki113/article/details/4033017 python 的内嵌time模板翻译及说明 一.简介 ...
- __init和__exit宏的作用
原文地址:http://blog.csdn.net/zhenwenxian/article/details/8564574 内核的部分函数带有__init和__exit宏,负责“初始化”和“清理收尾” ...
- linux下添加PATH环境变量
添加PATH环境变量,第1种方法:[root@lx_web_s1 ~]# export PATH=/usr/local/webserver/mysql/bin:$PATH 再次查看: [root@lx ...
- 当当开源sharding-jdbc,轻量级数据库分库分表中间件
近期,当当开源了数据库分库分表中间件sharding-jdbc. Sharding-JDBC是当当应用框架ddframe中,从关系型数据库模块dd-rdb中分离出来的数据库水平分片框架,实现透明化数据 ...
- php register_shutdown_function
register_shutdown_function — Register a function for execution on shutdown void register_shutdown_fu ...
- 254 shades of grey
254 shades of grey Description: Why would we want to stop to only 50 shades of grey? Let's see to ho ...
- C++中const小结
1.const修饰普通变量(非指针变量)const修饰变量,一般有两种写法:const TYPE value;TYPE const value;对于一个非指针的类型TYPE,这两种写法在本质上是一样的 ...
- MQ-传输方式Topic和Queue的对比
Jms规范里的两种message传输方式Topic和Queue,两者的对比如下表(): Topic Queue 概要 Publish Subscribe messaging 发布订阅消息 Poi ...
- js模仿jquery里的几个方法next, pre, nextAll, preAll
/*siblings函数, 选取node的所有兄弟节点*/ function siblings(node){ if(node.nodeType === 1){ node.flag = true; // ...
- ExecutorService与Executors例子的简单剖析
对于多线程有了一点了解之后,那么来看看java.lang.concurrent包下面的一些东西.在此之前,我们运行一个线程都是显式调用了Thread的start()方法.我们用concurrent下面 ...