经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
[树套树][学习笔记]
来源:cnblogs  作者:wxyww  时间:2018/12/12 9:54:36  对本文有异议

思想

树套树像他的名字一样,就是一棵树套另一棵树。用一棵外层树来维护一些区间之类的东西。然后外层树的每个节点都是一棵内层树。就这样

一道模板题

bzoj3196

思路

这是一道线段树套平衡树的模板题。外层用一棵线段树来维护区间操作。然后线段树的每个节点都是一棵平衡树

操作1:查询从l到r中比k小的数的个数,然后+1输出即可

操作2:二分一下答案,找排名小于等于k的最大值就行了

操作3:将原来的值先删去,然后加入新的值.

操作4:查询每个子区间中的前驱,然后最大的那个就是当前区间中的前驱

操作5:与操作4类似,查询每个子区间中的后继,然后最小的那个就是当前区间中的后继。

PS:在进行操作3的时候不要忘记将原来数组中的值也进行更改,不然以后再删除的时候会出错。在这个地方调了2h 2333

代码

  1. /*
  2. * @Author: wxyww
  3. * @Date: 2018-12-11 08:29:48
  4. * @Last Modified time: 2018-12-11 10:44:01
  5. */
  6. #include<cstdio>
  7. #include<iostream>
  8. #include<cstdlib>
  9. #include<cmath>
  10. #include<ctime>
  11. #include<bitset>
  12. using namespace std;
  13. typedef long long ll;
  14. #define ls TR[cur].ch[0]
  15. #define rs TR[cur].ch[1]
  16. const int N = 100000 + 100,INF = 2147483647;
  17. ll read() {
  18. ll x=0,f=1;char c=getchar();
  19. while(c<'0'||c>'9') {
  20. if(c=='-') f=-1;
  21. c=getchar();
  22. }
  23. while(c>='0'&&c<='9') {
  24. x=x*10+c-'0';
  25. c=getchar();
  26. }
  27. return x*f;
  28. }
  29. namespace treap {
  30. struct node {
  31. int val,siz,ch[2],id,cnt;
  32. }TR[N * 20];
  33. void up(int cur) {
  34. TR[cur].siz = TR[ls].siz + TR[rs].siz + TR[cur].cnt;
  35. }
  36. int tot = 0;
  37. void rotate(int &cur,int f) {
  38. int son = TR[cur].ch[f];
  39. TR[cur].ch[f] = TR[son].ch[f ^ 1];
  40. TR[son].ch[f ^ 1] = cur;
  41. up(cur);
  42. cur = son;
  43. up(cur);
  44. }
  45. void insert(int &cur,int val) {
  46. if(!cur) {
  47. cur = ++tot;
  48. TR[cur].val = val;
  49. TR[cur].siz = TR[cur].cnt = 1;
  50. TR[cur].id = rand();
  51. return;
  52. }
  53. TR[cur].siz++;
  54. if(val == TR[cur].val) {TR[cur].cnt++;return;}
  55. int d = val > TR[cur].val;
  56. insert(TR[cur].ch[d],val);
  57. if(TR[TR[cur].ch[d]].id < TR[cur].id) rotate(cur,d);
  58. }
  59. void del(int &cur,int val) {
  60. if(!cur) return;
  61. if(TR[cur].val == val) {
  62. if(TR[cur].cnt > 1) {TR[cur].cnt--;TR[cur].siz--;return;}
  63. if(!ls || !rs) {cur = ls + rs;return;}
  64. rotate(cur,TR[rs].id < TR[ls].id);
  65. del(cur,val);
  66. return;
  67. }
  68. TR[cur].siz--;
  69. del(TR[cur].ch[val > TR[cur].val],val);
  70. }
  71. int Rank(int cur,int val) {
  72. int ans = 0;
  73. while(cur) {
  74. if(val < TR[cur].val) cur = ls;
  75. else if(val == TR[cur].val) return ans + TR[ls].siz;
  76. else ans += TR[ls].siz + TR[cur].cnt,cur = rs;
  77. }
  78. return ans;
  79. }
  80. int pred(int cur,int val) {
  81. if(!cur) return -INF;
  82. if(val > TR[cur].val) return max(pred(rs,val),TR[cur].val);
  83. else return pred(ls,val);
  84. }
  85. int nex(int cur,int val) {
  86. if(!cur) return INF;
  87. if(val < TR[cur].val) return min(nex(ls,val),TR[cur].val);
  88. else return nex(rs,val);
  89. }
  90. }
  91. using namespace treap;
  92. int tree[N << 2];
  93. int a[N];
  94. int n;
  95. void build(int rt,int l,int r) {
  96. if(l == r) {
  97. insert(tree[rt],a[l]);
  98. return;
  99. }
  100. int mid = (l + r) >> 1;
  101. for(int i = l;i <= r;++i) insert(tree[rt],a[i]);
  102. build(rt << 1,l,mid);
  103. build(rt << 1 | 1,mid + 1,r);
  104. }
  105. void delet(int rt,int l,int r,int pos,int c) {
  106. if(l == r) {
  107. insert(tree[rt],c);
  108. del(tree[rt],a[pos]);
  109. return;
  110. }
  111. insert(tree[rt],c);
  112. del(tree[rt],a[pos]);
  113. int mid = (l + r) >> 1;
  114. if(pos <= mid) delet(rt << 1,l,mid,pos,c);
  115. else delet(rt << 1 | 1,mid + 1,r,pos,c);
  116. }
  117. int getrank(int rt,int l,int r,int L,int R,int val) {
  118. if(L <= l && R >= r) return Rank(tree[rt],val);
  119. int mid = (l + r) >> 1;
  120. int ans = 0;
  121. if(L <= mid) ans += getrank(rt << 1,l,mid,L,R,val);
  122. if(R > mid) ans += getrank(rt << 1 | 1,mid + 1,r,L, R,val);
  123. return ans;
  124. }
  125. int getpred(int rt,int l,int r,int L,int R,int val) {
  126. if(L <= l && R >= r) return pred(tree[rt],val);
  127. int mid = (l + r) >> 1;
  128. int ans = -INF;
  129. if(L <= mid) ans = max(ans,getpred(rt << 1,l,mid,L,R,val));
  130. if(R > mid) ans = max(ans,getpred(rt << 1 | 1,mid + 1,r,L, R,val));
  131. return ans;
  132. }
  133. int getnex(int rt,int l,int r,int L,int R,int val) {
  134. if(L <= l && R >= r) return nex(tree[rt],val);
  135. int mid = (l + r) >> 1;
  136. int ans = INF;
  137. if(L <= mid) ans = min(ans,getnex(rt << 1,l,mid,L,R,val));
  138. if(R > mid) ans = min(ans,getnex(rt << 1 | 1,mid + 1,r,L,R,val));
  139. return ans;
  140. }
  141. int MAX = -INF;
  142. int getkth(int L,int R,int x) {
  143. int l = 0,r = INF;
  144. int ans = 0;
  145. while(l <= r) {
  146. int mid = (l + r) >> 1;
  147. if(getrank(1,1,n,L,R,mid) + 1<= x) ans = mid,l = mid + 1;
  148. else r = mid - 1;
  149. }
  150. return ans;
  151. }
  152. int main() {
  153. n = read();
  154. int m = read();
  155. for(int i = 1;i <= n;++i) a[i] = read();
  156. build(1,1,n);
  157. while(m--) {
  158. int opt = read();
  159. if(opt == 1) {
  160. int l = read(),r = read(),k = read();
  161. printf("%d\n",getrank(1,1,n,l,r,k) + 1);
  162. }
  163. if(opt == 2) {
  164. int l = read(),r = read(),k = read();
  165. printf("%d\n",getkth(l,r,k));
  166. }
  167. if(opt == 3) {
  168. int pos = read(),k = read();
  169. delet(1,1,n,pos,k);
  170. a[pos] = k;//!!!
  171. }
  172. if(opt == 4) {
  173. int l = read(),r = read(),k = read();
  174. printf("%d\n",getpred(1,1,n,l,r,k));
  175. }
  176. if(opt == 5) {
  177. int l = read(),r = read(),k = read();
  178. printf("%d\n",getnex(1,1,n,l,r,k));
  179. }
  180. }
  181. return 0;
  182. }
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号