原理可以看hihocoder上面的讲解,很清楚,不多说了。

模板抄lrj训练指南上面的。

  1. /**
  2. Treap 实现 名次树
  3. 功能: 1.找到排名为k的元素
  4. 2.值为x的元素的名次
  5.  
  6. 初始化:Node* root = NULL;
  7. */
  8. #include <cstdlib>
  9. #include <cstdio>
  10. #include <cstring>
  11. #include <vector>
  12. using namespace std;
  13.  
  14. struct Node {
  15. Node * ch[]; // 0左子树 1右子树
  16. int r; // 随机优先级
  17. int v; // 值
  18. int s; // 以s为根的子树的大小
  19. Node(int v):v(v)
  20. {
  21. ch[] = ch[] = NULL;
  22. r = rand();
  23. s = ;
  24. }
  25. bool operator<(const Node& rhs) const { // 按随机优先级排序
  26. return r < rhs.r;
  27. }
  28. int cmp(int x) const
  29. {
  30. if (x == v) return -;
  31. return x < v ? : ;
  32. }
  33. void maintain() // 更新
  34. {
  35. s = ;
  36. if (ch[] != NULL) s += ch[]->s;
  37. if (ch[] != NULL) s += ch[]->s;
  38. }
  39. } ;
  40.  
  41. void rotate(Node* &o, int d) // d=0 代表左转, d=1代表右转
  42. {
  43. Node* k = o->ch[d^];
  44. o->ch[d^] = k->ch[d];
  45. k->ch[d] = o;
  46. o->maintain();
  47. k->maintain();
  48. o = k;
  49. }
  50.  
  51. void insert(Node* &o, int x) // o是根 x是插入的值
  52. {
  53. if (o == NULL) {
  54. o = new Node(x);
  55. } else {
  56. int d = (x < o->v ? : ); // 不用cmp函数因为可能有重复的值
  57. insert(o->ch[d], x);
  58. if ((o->ch[d]->r) > (o->r)) rotate(o, d^);
  59. }
  60. o->maintain();
  61. }
  62.  
  63. void remove(Node* &o, int x)
  64. {
  65. int d = o->cmp(x);
  66. if (d == -) {
  67. Node* u = o;
  68. if (o->ch[] != NULL && o->ch[] != NULL) {
  69. int d2 = ((o->ch[]->r) > (o->ch[]->r) ? : );
  70. rotate(o, d2);
  71. remove(o->ch[d2], x);
  72. } else {
  73. if (o->ch[] == NULL) o = o->ch[];
  74. else o = o->ch[];
  75. delete u;
  76. }
  77. } else {
  78. remove(o->ch[d], x);
  79. }
  80. if (o != NULL) o->maintain();
  81. }
  82.  
  83. int find(Node* o, int x) // 因为remove和insert都没有查值存不存在 记得操作之前调用find
  84. {
  85. while (o != NULL) {
  86. int d = o->cmp(x);
  87. if (d == -) return ;
  88. else o = o->ch[d];
  89. }
  90. return ;
  91. }
  92.  
  93. int kth(Node* &o, int k, int fg) // fg=1第k大的值 fg=0第k小的值 返回0表示没找到
  94. {
  95. if (o == NULL || k <= || k > o->s) return ;
  96. int s = (o->ch[fg] == NULL ? : o->ch[fg]->s);
  97. if (k == s+) return o->v;
  98. else if (k <= s) return kth(o->ch[fg], k, fg);
  99. else return kth(o->ch[fg^], k-s-, fg);
  100. }
  101.  
  102. int prv(Node* &o, int x) // 查找x前面的元素 (<x的最大值
  103. {
  104. if (o == NULL) return -;
  105. if (x <= o->v) return prv(o->ch[], x);
  106. int ans = prv(o->ch[], x);
  107.  
  108. return ans == - ? o->v : ans;
  109. }
  110.  
  111. int nxt(Node* &o, int x) // 查找x后面的元素 (>x的最大值
  112. {
  113. if (o == NULL) return -;
  114. if (x >= o->v) return nxt(o->ch[], x);
  115. int ans = nxt(o->ch[], x);
  116. return ans == - ? o->v : ans;
  117. }
  118.  
  119. void mergeto(Node* &src, Node* &dest) // 合并两棵树 把src加到dest上 src和dest都是树的根
  120. {
  121. if (src->ch[] != NULL) mergeto(src->ch[], dest);
  122. if (src->ch[] != NULL) mergeto(src->ch[], dest);
  123. insert(dest, src->v);
  124. delete src;
  125. src = NULL;
  126. }
  127.  
  128. void print(Node* &o)
  129. {
  130. if (o == NULL) return ;
  131. print(o->ch[]);
  132. printf("%d ", o->v);
  133. print(o->ch[]);
  134. }
  135.  
  136. int main()
  137. {
  138. Node* root = NULL;
  139. insert(root, );
  140. insert(root, );
  141. insert(root, );
  142. insert(root, );
  143. remove(root, );
  144. print(root);
  145. return ;
  146. }

例题:

上面hihocoder的例题,这个代码是照着讲解自己写的

  1. //Treap.cpp
  2.  
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6.  
  7. const int N = ;
  8.  
  9. struct Treap {
  10. int father, left, right;
  11. int key, weight;
  12. void init(int k, int w, int fa) {
  13. left = right = -;
  14. father = fa, key = k, weight = w;
  15. }
  16. } tp[N];
  17. int root;
  18. int treap_cnt;
  19.  
  20. int new_treap(int k, int w, int fa = -)
  21. {
  22. tp[treap_cnt].init(k, w, fa);
  23. return treap_cnt++;
  24. }
  25.  
  26. void left_rotate(int a) // 左旋 把节点A的右儿子节点B转到A的父亲节点
  27. {
  28. int b = tp[a].right;
  29. tp[b].father = tp[a].father;
  30. if (tp[tp[a].father].left == a) { // 判断a是父节点的左儿子还是右儿子 并用b替换
  31. tp[tp[a].father].left = b;
  32. } else {
  33. tp[tp[a].father].right = b;
  34. }
  35. tp[a].right = tp[b].left;
  36. if (tp[b].left != -) tp[tp[b].left].father = a;
  37. tp[b].left = a;
  38. tp[a].father = b;
  39. }
  40.  
  41. void right_rotate(int a) // 右旋 把节点A的左儿子节点B转到A的父亲节点
  42. {
  43. int b = tp[a].left;
  44. tp[b].father = tp[a].father;
  45. if (tp[tp[a].father].left == a) tp[tp[a].father].left = b;
  46. else tp[tp[a].father].right = b;
  47. tp[a].left = tp[b].right;
  48. if (tp[b].right != -) tp[tp[b].right].father = a;
  49. tp[b].right = a;
  50. tp[a].father = b;
  51. }
  52.  
  53. int insert(int a, int key)
  54. {
  55. if (key < tp[a].key) {
  56. if (tp[a].left == -) {
  57. tp[a].left = new_treap(key, rand(), a);
  58. return tp[a].left;
  59. } else {
  60. return insert(tp[a].left, key);
  61. }
  62. } else {
  63. if (tp[a].right == -) {
  64. tp[a].right = new_treap(key, rand(), a);
  65. return tp[a].right;
  66. } else {
  67. return insert(tp[a].right, key);
  68. }
  69. }
  70. }
  71.  
  72. void rotate(int a) // 维持小顶堆
  73. {
  74. int fa = tp[a].father;
  75. while (fa != -) {
  76. if (tp[a].weight < tp[fa].weight) {
  77. if (a == tp[fa].left) right_rotate(fa);
  78. else left_rotate(fa);
  79. fa = tp[a].father;
  80. } else {
  81. break;
  82. }
  83. }
  84. if (fa == -) root = a;
  85. }
  86.  
  87. int find(int a, int key)
  88. {
  89. int cur = a, pre = -;
  90. while (cur != -) {
  91. if (tp[cur].key > key) {
  92. pre = cur;
  93. cur = tp[cur].left;
  94. } else if (tp[cur].key < key) {
  95. pre = cur;
  96. cur = tp[cur].right;
  97. } else {
  98. return key;
  99. }
  100. }
  101. while (pre != -) {
  102. if (tp[pre].key < key) return tp[pre].key;
  103. pre = tp[pre].father;
  104. }
  105. return -;
  106. }
  107.  
  108. void print(int a)
  109. {
  110. if (a == -) return;
  111. print(tp[a].left);
  112. printf("%d(%d) ", a, tp[a].key);
  113. print(tp[a].right);
  114. }
  115.  
  116. int main(int argc, char const *argv[])
  117. {
  118. //freopen("in", "r", stdin);
  119. root = -;
  120. treap_cnt = ;
  121. int n;
  122. char op[];
  123. int k;
  124. scanf("%d", &n);
  125. while (n--) {
  126. scanf("%s%d", op, &k);
  127. if (*op == 'I') {
  128. if (root == -) root = new_treap(k, rand());
  129. else rotate(insert(root, k));
  130. } else {
  131. printf("%d\n", find(root, k));
  132. }
  133. }
  134. return ;
  135. }

poj1442,直接套模板,比较简单

  1. /**
  2. Treap 实现 名次树
  3. 功能: 1.找到排名为k的元素
  4. 2.值为x的元素的名次
  5. */
  6. #include <cstdlib>
  7. #include <cstdio>
  8. #include <cstring>
  9. #include <vector>
  10. using namespace std;
  11.  
  12. struct Node {
  13. Node * ch[]; // 0左子树 1右子树
  14. int r; // 随机优先级
  15. int v; // 值
  16. int s; // 以s为根的子树的大小
  17. Node(int v):v(v)
  18. {
  19. ch[] = ch[] = NULL;
  20. r = rand();
  21. s = ;
  22. }
  23. bool operator<(const Node& rhs) const { // 按随机优先级排序
  24. return r < rhs.r;
  25. }
  26. int cmp(int x) const
  27. {
  28. if (x == v) return -;
  29. return x < v ? : ;
  30. }
  31. void maintain() // 更新
  32. {
  33. s = ;
  34. if (ch[] != NULL) s += ch[]->s;
  35. if (ch[] != NULL) s += ch[]->s;
  36. }
  37. } ;
  38.  
  39. void rotate(Node* &o, int d) // d=0 代表左转, d=1代表右转
  40. {
  41. Node* k = o->ch[d^];
  42. o->ch[d^] = k->ch[d];
  43. k->ch[d] = o;
  44. o->maintain();
  45. k->maintain();
  46. o = k;
  47. }
  48.  
  49. void insert(Node* &o, int x) // o是根 x是插入的值
  50. {
  51. if (o == NULL) {
  52. o = new Node(x);
  53. } else {
  54. int d = (x < o->v ? : ); // 不用cmp函数因为可能有重复的值
  55. insert(o->ch[d], x);
  56. if ((o->ch[d]->r) > (o->r)) rotate(o, d^);
  57. }
  58. o->maintain();
  59. }
  60.  
  61. void remove(Node* &o, int x)
  62. {
  63. int d = o->cmp(x);
  64. if (d == -) {
  65. Node* u = o;
  66. if (o->ch[] != NULL && o->ch[] != NULL) {
  67. int d2 = ((o->ch[]->r) > (o->ch[]->r) ? : );
  68. rotate(o, d2);
  69. remove(o->ch[d2], x);
  70. } else {
  71. if (o->ch[] == NULL) o = o->ch[];
  72. else o = o->ch[];
  73. delete u;
  74. }
  75. } else {
  76. remove(o->ch[d], x);
  77. }
  78. if (o != NULL) o->maintain();
  79. }
  80.  
  81. int find(Node* &o, int x) // 因为remove和insert都没有查值存不存在 记得操作之前调用find
  82. {
  83. while (o != NULL) {
  84. int d = o->cmp(x);
  85. if (d == -) return ; // exist
  86. else o = o->ch[d];
  87. }
  88. return ; // not exist
  89. }
  90.  
  91. int kth(Node* &o, int k, int fg) // fg=1第k大的值 fg=0第k小的值 返回0表示没找到
  92. {
  93. if (o == NULL || k <= || k > o->s) return ;
  94. int s = (o->ch[fg] == NULL ? : o->ch[fg]->s);
  95. if (k == s+) return o->v;
  96. else if (k <= s) return kth(o->ch[fg], k, fg);
  97. else return kth(o->ch[fg^], k-s-, fg);
  98. }
  99.  
  100. void mergeto(Node* &src, Node* &dest)
  101. {
  102. if (src->ch[] != NULL) mergeto(src->ch[], dest);
  103. if (src->ch[] != NULL) mergeto(src->ch[], dest);
  104. insert(dest, src->v);
  105. delete src;
  106. src = NULL;
  107. }
  108.  
  109. const int N = ;
  110. int a[N];
  111. int main()
  112. {
  113. //freopen("in", "r", stdin);
  114. int m, n;
  115. while (~scanf("%d%d", &m, &n)) {
  116. Node* root = NULL;
  117. for (int i = ; i <= m; ++i) {
  118. scanf("%d", a+i);
  119. }
  120. int x = , u, cnt = ;
  121. for (int i = ; i < n; ++i) {
  122. scanf("%d", &u);
  123. while (cnt < u) {
  124. insert(root, a[++cnt]);
  125. }
  126. printf("%d\n", kth(root, ++x, ));
  127. }
  128. }
  129. return ;
  130. }

hdu4557

每个结点加了一个元素t,排序查找都要考虑t

  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <cstdio>
  4. #include <cstring>
  5. #include <map>
  6. #include <vector>
  7. using namespace std;
  8.  
  9. struct Node {
  10. Node * ch[]; // 0左子树 1右子树
  11. int r; // 随机优先级
  12. int v; // 值
  13. int t;
  14. int s; // 以s为根的子树的大小
  15. Node(int v, int t):v(v), t(t)
  16. {
  17. ch[] = ch[] = NULL;
  18. r = rand();
  19. s = ;
  20. }
  21. bool operator<(const Node& rhs) const { // 按随机优先级排序
  22. if (r == rhs.r) return t < rhs.t;
  23. return r < rhs.r;
  24. }
  25. int cmp(int x, int y) const
  26. {
  27. if (x == v && y == t) return -;
  28. if (x == v) return y < t ? : ;
  29. return x < v ? : ;
  30. }
  31. void maintain() // 更新
  32. {
  33. s = ;
  34. if (ch[] != NULL) s += ch[]->s;
  35. if (ch[] != NULL) s += ch[]->s;
  36. }
  37. } ;
  38.  
  39. void rotate(Node* &o, int d) // d=0 代表左转, d=1代表右转
  40. {
  41. Node* k = o->ch[d^];
  42. o->ch[d^] = k->ch[d];
  43. k->ch[d] = o;
  44. o->maintain();
  45. k->maintain();
  46. o = k;
  47. }
  48.  
  49. void insert(Node* &o, int x, int y) // o是根 x是插入的值
  50. {
  51. if (o == NULL) {
  52. o = new Node(x, y);
  53. } else {
  54. int d = o->cmp(x, y);
  55. insert(o->ch[d], x, y);
  56. if ((o->ch[d]->r) > (o->r)) rotate(o, d^);
  57. }
  58. o->maintain();
  59. }
  60.  
  61. void remove(Node* &o, int x, int y)
  62. {
  63. int d = o->cmp(x, y);
  64. if (d == -) {
  65. Node* u = o;
  66. if (o->ch[] != NULL && o->ch[] != NULL) {
  67. int d2 = ((o->ch[]->r) > (o->ch[]->r) ? : );
  68. rotate(o, d2);
  69. remove(o->ch[d2], x, y);
  70. } else {
  71. if (o->ch[] == NULL) o = o->ch[];
  72. else o = o->ch[];
  73. delete u;
  74. }
  75. } else {
  76. remove(o->ch[d], x, y);
  77. }
  78. if (o != NULL) o->maintain();
  79. }
  80.  
  81. int nxt(Node* &o, int x, int &res) // 查找x后面的元素 (>=x的最小值
  82. {
  83. if (o == NULL) return -;
  84. if (o->v < x) return nxt(o->ch[], x, res);
  85. res = o->v;
  86. int ans = nxt(o->ch[], x, res);
  87. return ans == - ? o->t : ans;
  88. }
  89.  
  90. void print(Node* &o)
  91. {
  92. if (o == NULL) return ;
  93. print(o->ch[]);
  94. printf("%d ", o->v);
  95. print(o->ch[]);
  96. }
  97.  
  98. int main()
  99. {
  100. freopen("in", "r", stdin);
  101. int T;
  102. cin >> T;
  103. int cas = ;
  104. while (T--) {
  105. printf("Case #%d:\n", ++cas);
  106. int n;
  107. cin >> n;
  108. char op[];
  109. string name;
  110. int abi, res;
  111. Node* root = NULL;
  112. map<int, string> mp;
  113. for (int i = ; i < n; ++i) {
  114. scanf("%s", op);
  115. if (*op == 'A') {
  116. cin >> name;
  117. scanf("%d", &abi);
  118. mp[i] = name;
  119. insert(root, abi, i);
  120. printf("%d\n", root->s);
  121. } else {
  122. scanf("%d", &abi);
  123. int ans = nxt(root, abi, res);
  124. if (ans == -) printf("WAIT...\n");
  125. else {
  126. cout << mp[ans] << endl;
  127. remove(root, res, ans);
  128. }
  129. }//printf("debug:"); print(root); printf("\n");
  130. }
  131. }
  132. }

Treap 模板 poj1442&hdu4557的更多相关文章

  1. BZOJ 1588: Treap 模板

    1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 12171  Solved: 4352 Description ...

  2. [luogu3369]普通平衡树(treap模板)

    解题关键:treap模板保存. #include<cstdio> #include<cstring> #include<algorithm> #include< ...

  3. 平衡树Treap模板与原理

    这次我们来讲一讲Treap(splay以后再更) 平衡树是一种排序二叉树(或二叉搜索树),所以排序二叉树可以迅速地判断两个值的大小,当然操作肯定不止那么多(不然我们还学什么). 而平衡树在排序二叉树的 ...

  4. POJ1442-查询第K大-Treap模板题

    模板题,以后要学splay,大概看一下treap就好了. #include <cstdio> #include <algorithm> #include <cstring ...

  5. Treap 模板

    感觉平衡树也没有以前想的那么玄乎,(其实set超好用的),非旋式Treap挺好理解,和可并堆,二叉搜索树有很大联系 推荐博客:http://memphis.is-programmer.com/post ...

  6. 【Treap模板详细注释】BZOJ3224-普通平衡树

    模板题:D错因见注释 #include<iostream> #include<cstdio> #include<cstring> #include<algor ...

  7. 非旋treap模板

    bzoj3580 非旋转treap 在大神教导下发现split一段区间时先split右边再split左边比较好写 #include <cstdio> #include <cstdli ...

  8. 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[ ...

  9. Treap模板

    平衡树总是有用的,set由于过度封装没有办法实现找比x小的元素有多少个,这就显得很不方便了,所以封装了个Treap,万一以后用的着呢- -01 #pragma warning(disable:4996 ...

随机推荐

  1. python time模块详解

    python time模块详解 转自:http://blog.csdn.net/kiki113/article/details/4033017 python 的内嵌time模板翻译及说明  一.简介 ...

  2. __init和__exit宏的作用

    原文地址:http://blog.csdn.net/zhenwenxian/article/details/8564574 内核的部分函数带有__init和__exit宏,负责“初始化”和“清理收尾” ...

  3. linux下添加PATH环境变量

    添加PATH环境变量,第1种方法:[root@lx_web_s1 ~]# export PATH=/usr/local/webserver/mysql/bin:$PATH 再次查看: [root@lx ...

  4. 当当开源sharding-jdbc,轻量级数据库分库分表中间件

    近期,当当开源了数据库分库分表中间件sharding-jdbc. Sharding-JDBC是当当应用框架ddframe中,从关系型数据库模块dd-rdb中分离出来的数据库水平分片框架,实现透明化数据 ...

  5. php register_shutdown_function

    register_shutdown_function — Register a function for execution on shutdown void register_shutdown_fu ...

  6. 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 ...

  7. C++中const小结

    1.const修饰普通变量(非指针变量)const修饰变量,一般有两种写法:const TYPE value;TYPE const value;对于一个非指针的类型TYPE,这两种写法在本质上是一样的 ...

  8. MQ-传输方式Topic和Queue的对比

    Jms规范里的两种message传输方式Topic和Queue,两者的对比如下表():   Topic Queue 概要 Publish  Subscribe messaging 发布订阅消息 Poi ...

  9. js模仿jquery里的几个方法next, pre, nextAll, preAll

    /*siblings函数, 选取node的所有兄弟节点*/ function siblings(node){ if(node.nodeType === 1){ node.flag = true; // ...

  10. ExecutorService与Executors例子的简单剖析

    对于多线程有了一点了解之后,那么来看看java.lang.concurrent包下面的一些东西.在此之前,我们运行一个线程都是显式调用了Thread的start()方法.我们用concurrent下面 ...