浅谈树状数组与线段树:https://www.cnblogs.com/AKMer/p/9946944.html

浅谈\(Splay\):https://www.cnblogs.com/AKMer/p/9979592.html

题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3196

树套树模板题,外层用一个位置线段树,内层用一个平衡树即可解决。

查第\(k\)大是谁需要在外面套一个二分。这题比较卡,反正我是勉勉强强跑过去的……

时间复杂度:\(O(nlog^3n)\)

空间复杂度:\(O(nlogn)\)

代码如下:

  1. #include <cstdio>
  2. #include <algorithm>
  3. using namespace std;
  4. const int maxn=5e4+5,inf=2147483647;
  5. int a[maxn];
  6. int n,m,mn=1e9,mx=-1e9;
  7. int read() {
  8. int x=0,f=1;char ch=getchar();
  9. for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
  10. for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
  11. return x*f;
  12. }
  13. struct Splay {
  14. int tot;
  15. int son[maxn*25][2],fa[maxn*25];
  16. int siz[maxn*25],cnt[maxn*25],val[maxn*25];
  17. int newnode(int v) {
  18. val[++tot]=v;
  19. siz[tot]=cnt[tot]=1;
  20. return tot;
  21. }
  22. int find(int rt,int v) {
  23. int u=rt;
  24. while(val[u]!=v) {
  25. if(val[u]>v) {if(son[u][0])u=son[u][0];else break;}
  26. if(val[u]<v) {if(son[u][1])u=son[u][1];else break;}
  27. }
  28. return u;
  29. }
  30. int t(int u) {
  31. return son[fa[u]][1]==u;
  32. }
  33. void updata(int u) {
  34. siz[u]=siz[son[u][0]]+cnt[u]+siz[son[u][1]];
  35. }
  36. void rotate(int u) {
  37. int ret=t(u),f=fa[u],s=son[u][ret^1];
  38. son[f][ret]=s;if(s)fa[s]=f;son[u][ret^1]=f;
  39. fa[u]=fa[f];if(fa[f])son[fa[f]][t(f)]=u;
  40. fa[f]=u;updata(f);updata(u);
  41. }
  42. void splay(int &rt,int u) {
  43. while(fa[u]) {
  44. if(fa[fa[u]]) {
  45. if(t(fa[u])!=t(u))rotate(u);
  46. else rotate(fa[u]);
  47. }
  48. rotate(u);
  49. }
  50. rt=u;
  51. }
  52. void ins(int &rt,int v) {
  53. if(!rt) {rt=newnode(v);return;}
  54. int u=find(rt,v);
  55. if(val[u]==v) {siz[u]++,cnt[u]++,splay(rt,u);return;}
  56. fa[newnode(v)]=u;son[u][v>val[u]]=tot;splay(rt,tot);
  57. }
  58. int get_rk(int &rt,int v) {
  59. int u=find(rt,v);splay(rt,u);
  60. if(val[u]>=v)return siz[son[u][0]];
  61. return siz[son[u][0]]+cnt[u];
  62. }
  63. void del(int &rt,int v) {
  64. int u=find(rt,v);splay(rt,u);
  65. if(cnt[u]>1) {cnt[u]--,siz[u]--;return;}
  66. if(!son[u][0]) {rt=son[u][1],fa[rt]=0;return;}
  67. if(!son[u][1]) {rt=son[u][0],fa[rt]=0;return;}
  68. int node=son[u][0];while(son[node][1])node=son[node][1];
  69. fa[son[u][0]]=0;splay(rt,node);
  70. son[node][1]=son[u][1];fa[son[u][1]]=node;
  71. updata(node);
  72. }
  73. int get_pre(int &rt,int v) {
  74. int u=find(rt,v);splay(rt,u);
  75. if(val[u]<v)return val[u];
  76. int node=son[u][0];
  77. while(son[node][1])node=son[node][1];
  78. if(node)return val[node];
  79. return -inf;
  80. }
  81. int get_suc(int &rt,int v) {
  82. int u=find(rt,v);splay(rt,u);
  83. if(val[u]>v)return val[u];
  84. int node=son[u][1];
  85. while(son[node][0])node=son[node][0];
  86. if(node)return val[node];
  87. return inf;
  88. }
  89. }S;
  90. struct segment_tree {
  91. int rt[maxn<<2];
  92. void build(int p,int l,int r) {
  93. for(int i=l;i<=r;i++)
  94. S.ins(rt[p],a[i]);
  95. if(l==r)return;
  96. int mid=(l+r)>>1;
  97. build(p<<1,l,mid);
  98. build(p<<1|1,mid+1,r);
  99. }
  100. int query_rk(int p,int l,int r,int L,int R,int v) {
  101. if(L<=l&&r<=R)return S.get_rk(rt[p],v);
  102. int mid=(l+r)>>1,res=0;
  103. if(L<=mid)res=query_rk(p<<1,l,mid,L,R,v);
  104. if(R>mid)res+=query_rk(p<<1|1,mid+1,r,L,R,v);
  105. return res;
  106. }
  107. void change(int p,int l,int r,int pos,int v_before,int v_after) {
  108. S.del(rt[p],v_before);S.ins(rt[p],v_after);
  109. if(l==r)return; int mid=(l+r)>>1;
  110. if(pos<=mid)change(p<<1,l,mid,pos,v_before,v_after);
  111. else change(p<<1|1,mid+1,r,pos,v_before,v_after);
  112. }
  113. int query_pre(int p,int l,int r,int L,int R,int v) {
  114. if(L<=l&&r<=R)return S.get_pre(rt[p],v);
  115. int mid=(l+r)>>1,res=-inf;
  116. if(L<=mid)res=max(res,query_pre(p<<1,l,mid,L,R,v));
  117. if(R>mid)res=max(res,query_pre(p<<1|1,mid+1,r,L,R,v));
  118. return res;
  119. }
  120. int query_suc(int p,int l,int r,int L,int R,int v) {
  121. if(L<=l&&r<=R)return S.get_suc(rt[p],v);
  122. int mid=(l+r)>>1,res=inf;
  123. if(L<=mid)res=min(res,query_suc(p<<1,l,mid,L,R,v));
  124. if(R>mid)res=min(res,query_suc(p<<1|1,mid+1,r,L,R,v));
  125. return res;
  126. }
  127. }T;
  128. int main() {
  129. n=read(),m=read();
  130. for(int i=1;i<=n;i++)
  131. a[i]=read(),mn=min(mn,a[i]),mx=max(mx,a[i]);
  132. T.build(1,1,n);
  133. for(int i=1;i<=m;i++) {
  134. int opt=read(),l,r,pos,k;
  135. if(opt==3)pos=read(),k=read();
  136. else l=read(),r=read(),k=read();
  137. if(opt==1)printf("%d\n",T.query_rk(1,1,n,l,r,k)+1);
  138. if(opt==2) {
  139. int L=mn,R=mx;
  140. while(L<R) {
  141. int mid=(L+R+1)>>1;
  142. int rk=T.query_rk(1,1,n,l,r,mid)+1;
  143. if(rk>k)R=mid-1;
  144. else L=mid;
  145. }
  146. printf("%d\n",L);
  147. }
  148. if(opt==3)T.change(1,1,n,pos,a[pos],k),a[pos]=k,mn=min(mn,k),mx=max(mx,k);
  149. if(opt==4)printf("%d\n",T.query_pre(1,1,n,l,r,k));
  150. if(opt==5)printf("%d\n",T.query_suc(1,1,n,l,r,k));
  151. }
  152. return 0;
  153. }

BZOJ3196:二逼平衡树的更多相关文章

  1. BZOJ3196二逼平衡树——线段树套平衡树(treap)

    此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...

  2. bzoj3196 二逼平衡树 树状数组套线段树

    题目传送门 思路:树状数组套线段树模板题. 什么是树状数组套线段树,普通的树状数组每个点都是一个权值,而这里的树状数组每个点都是一颗权值线段树,我们用前缀差分的方法求得每个区间的各种信息, 其实关键就 ...

  3. bzoj3196 二逼平衡树 树套树(线段树套Treap)

    Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 4697  Solved: 1798[Submit][Status][D ...

  4. bzoj3196 二逼平衡树

    题目链接 平衡树系列最后一题 坑啊 10s时间限制跑了9764ms...还是要学一学bit套主席树啦... 经典的线段树套treap...至于第一发为什么要TLE(我不会告诉你treap插入的时候忘了 ...

  5. BZOJ3196 二逼平衡树 ZKW线段树套vector(滑稽)

    我实在是不想再打一遍树状数组套替罪羊树了... 然后在普通平衡树瞎逛的时候找到了以前看过vector题解 于是我想:为啥不把平衡树换成vector呢??? 然后我又去学了一下ZKW线段树 就用ZKW线 ...

  6. [BZOJ3196] 二逼平衡树 [权值线段树套位置平衡树]

    题面 洛咕题面 思路 没错我就是要不走寻常路! 看看那些外层位置数据结构,必须二分的,$O(n\log^3 n)$的做法吧! 看看那些cdq分治/树状数组套线段树的,空间$O(n\log^2 n)$挤 ...

  7. BZOJ3196 二逼平衡树 【线段树套平衡树】

    题目 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱 ...

  8. BZOJ3196——二逼平衡树

    1.题目大意:给你一个序列,有5种操作,都有什么呢... 1> 区间第k小 这个直接用二分+树套树做 2> 区间小于k的有多少 这个直接用树套树做 3> 单点修改 这个直接用树套树做 ...

  9. luogu3380/bzoj3196 二逼平衡树 (树状数组套权值线段树)

    带修改区间K大值 这题有很多做法,我的做法是树状数组套权值线段树,修改查询的时候都是按着树状数组的规则找出那log(n)个线段树根,然后一起往下做 时空都是$O(nlog^2n)$的(如果离散化了的话 ...

  10. BZOJ3196:二逼平衡树(线段树套Splay)

    Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在 ...

随机推荐

  1. Bootstrap学习速查表(三) 表单

    表单中常见的元素主要包括:文本输入框.下拉选择框.单选按钮.复选按钮.文本域和按钮等. 一.基础表单 1.初始化:对于基础表单,Bootstrap并未对其做太多的定制性效果设计,仅仅对表单内的fiel ...

  2. Java异常 - Exception总结

    这篇blog总结的比较详细了. 如下图所示,在Java中所有异常的基类均为Throwable类.有两个子类,分别为Exception和Error.其中Error主要由JVM处理,比如OutOfMemo ...

  3. 搜狐新闻APP是如何使用HUAWEI DevEco IDE快速集成HUAWEI HiAI Engine

    6月12日,搜狐新闻APP最新版本在华为应用市场正式上线啦! 那么,这一版本的搜狐新闻APP有什么亮点呢? 先抛个图,来直接感受下—— ​ 模糊图片,瞬间清晰! 效果杠杠的吧. 而藏在这项神操作背后的 ...

  4. Net中的代码规范工具及使用

    Net中的代码规范工具及使用 https://www.cnblogs.com/selimsong/p/9209254.html 上一篇文章介绍了编码标准中一些常用的工具,本篇就具体来介绍如何使用它们来 ...

  5. erlang动态生成随机key

    取随机数,举个例子: 获取动态随机key值16位(key的范围是由"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678 ...

  6. 【BZOJ2083】[Poi2010]Intelligence test 二分

    [BZOJ2083][Poi2010]Intelligence test Description 霸中智力测试机构的一项工作就是按照一定的规则删除一个序列的数字,得到一个确定的数列.Lyx很渴望成为霸 ...

  7. 连通性 保证f具有介值性质

  8. RANDOM 的用法

    random 用法 1.利用RANDOM取随机数 shell有一个环境变量RANDOM,范围是0--32767 如果我们想要产生0-25范围内的数:$(($RANDOM%26),在$(()) 是可以省 ...

  9. CUDA: 常量内存与事件

    常量内存: 常量内存用于保存在核函数执行期间不会发生变化的数据,在变量面前添加  __constant__  修饰符: __constant__  Sphere  s[SPHERES]; cudaMe ...

  10. ubuntu nohup命令用法

    让程序在后台运行 该命令的一般形式nohup command & 程序在后台运行并打印日志 nohup ./china_fund.py > china_fund.file 2>&a ...