思路

若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名

若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数

若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k

若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱

若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

树套树

区间操作可以用我们熟悉的线段树

线段树上每个点 维护对应区间[l,r]的一颗平衡树

线段树深度logn,每层要维护n个节点,所以treap的内存是nlogn

操作2的话,二分顺便用操作1check就好

二分的答案一定是在序列中的 ,复杂度\(log^{3}n\)(真的2b啊,什么复杂度)

其他具体操作就不啰嗦了(复杂度普遍\(log^{2}n\))

而n=5e4的时候\(log^{2}n\)和\(\sqrt{n}\)基本是相等的(分界线)

注意

线段树套平衡树

平衡树的种类也要选好

fhq-treap这种常数就比较大

普通treap就不错

splay也阔以

fhq-treap代码

  1. #include <bits/stdc++.h>
  2. #define FOR(i,a,b) for(int i=a;i<=b;++i)
  3. using namespace std;
  4. const int maxn=5e4+7;
  5. const int inf=0x7fffffff;
  6. inline int read() {
  7. int x=0,f=1;char s=getchar();
  8. for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
  9. for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
  10. return x*f;
  11. }
  12. int w[maxn];
  13. int ch[maxn*40][2],val[maxn*40],pri[maxn*40],siz[maxn*40],cnt;
  14. namespace fhq_treap {
  15. void pushup(int x) {
  16. siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
  17. }
  18. int new_node(int x) {
  19. val[++cnt]=x;
  20. pri[cnt]=rand();
  21. siz[cnt]=1;
  22. return cnt;
  23. }
  24. int merge(int x,int y) {
  25. if(!x||!y) return x+y;
  26. if(pri[x]<pri[y]) {
  27. ch[x][1]=merge(ch[x][1],y);
  28. pushup(x);return x;
  29. } else {
  30. ch[y][0]=merge(x,ch[y][0]);
  31. pushup(y);return y;
  32. }
  33. }
  34. void split(int now,int k,int &x,int &y) {
  35. if(!now) x=y=0;
  36. else {
  37. if(val[now]<=k)
  38. x=now,split(ch[now][1],k,ch[x][1],y);
  39. else
  40. y=now,split(ch[now][0],k,x,ch[y][0]);
  41. pushup(now);
  42. }
  43. }
  44. int find(int &rt,int a) {
  45. int x,y;
  46. split(rt,a-1,x,y);
  47. int tmp=siz[x];
  48. rt=merge(x,y);
  49. return tmp;
  50. }
  51. int k_th(int now,int k) {
  52. if(siz[now]<k||siz[now]==0||k==0) return 0x7fffffff;
  53. while(233) {
  54. if(siz[ch[now][0]]+1==k) return val[now];
  55. if(siz[ch[now][0]]>=k) now=ch[now][0];
  56. else k-=siz[ch[now][0]]+1,now=ch[now][1];
  57. }
  58. }
  59. void insert(int &rt,int a) {
  60. int x,y;
  61. split(rt,a,x,y);
  62. rt=merge(merge(x,new_node(a)),y);
  63. }
  64. void delet(int &rt,int a) {
  65. int x,y,z;
  66. split(rt,a,x,z);
  67. split(x,a-1,x,y);
  68. y=merge(ch[y][0],ch[y][1]);
  69. rt=merge(merge(x,y),z);
  70. }
  71. int qq(int &rt,int a) {
  72. int x,y,tmp;
  73. split(rt,a-1,x,y);
  74. tmp=k_th(x,siz[x]);
  75. rt=merge(x,y);
  76. return tmp==inf ? -inf : tmp;
  77. }
  78. int hj(int &rt,int a) {
  79. int x,y,tmp;
  80. split(rt,a,x,y);
  81. tmp=k_th(y,1);
  82. rt=merge(x,y);
  83. return tmp;
  84. }
  85. }
  86. struct node {
  87. int l,r,rt;
  88. }e[maxn<<2];
  89. void build(int l,int r,int rt) {
  90. e[rt].l=l,e[rt].r=r;
  91. FOR(i,l,r) fhq_treap::insert(e[rt].rt,w[i]);
  92. if(l==r) return;
  93. int mid=(l+r)>>1;
  94. build(l,mid,rt<<1);
  95. build(mid+1,r,rt<<1|1);
  96. }
  97. void modify(int L,int k,int rt) {
  98. fhq_treap::delet(e[rt].rt,w[L]);
  99. fhq_treap::insert(e[rt].rt,k);
  100. if(e[rt].l==e[rt].r) return;
  101. int mid=(e[rt].l+e[rt].r)>>1;
  102. if(L<=mid) modify(L,k,rt<<1);
  103. else modify(L,k,rt<<1|1);
  104. }
  105. int find(int L,int R,int k,int rt) {
  106. if(L<=e[rt].l&&e[rt].r<=R)
  107. return fhq_treap::find(e[rt].rt,k);
  108. int mid=(e[rt].l+e[rt].r)>>1,ans=0;
  109. if(L<=mid) ans+=find(L,R,k,rt<<1);
  110. if(R>mid) ans+=find(L,R,k,rt<<1|1);
  111. return ans;
  112. }
  113. int qq(int L,int R,int a,int rt) {
  114. if(L<=e[rt].l&&e[rt].r<=R) {
  115. return fhq_treap::qq(e[rt].rt,a);
  116. }
  117. int mid=(e[rt].l+e[rt].r)>>1,ans=-inf;
  118. if(L<=mid) ans=max(ans,qq(L,R,a,rt<<1));
  119. if(R>mid) ans=max(ans,qq(L,R,a,rt<<1|1));
  120. return ans;
  121. }
  122. int hj(int L,int R,int a,int rt) {
  123. if(L<=e[rt].l&&e[rt].r<=R) {
  124. return fhq_treap::hj(e[rt].rt,a);
  125. }
  126. int mid=(e[rt].l+e[rt].r)>>1,ans=inf;
  127. if(L<=mid) ans=min(ans,hj(L,R,a,rt<<1));
  128. if(R>mid) ans=min(ans,hj(L,R,a,rt<<1|1));
  129. return ans;
  130. }
  131. int main() {
  132. srand(time(NULL));
  133. int n=read(),m=read();
  134. FOR(i,1,n) w[i]=read();
  135. build(1,n,1);
  136. FOR(i,1,m) {
  137. int opt=read();
  138. if(opt==1) {
  139. int l=read(),r=read(),k=read();
  140. cout<<find(l,r,k,1)+1<<"\n";
  141. } else
  142. if(opt==2) {
  143. int l=read(),r=read(),k=read();
  144. int L=0,R=1e8+5,ans=0;
  145. while(L<=R) {
  146. int mid=(L+R)>>1;
  147. if(find(l,r,mid,1)+1<=k) ans=mid,L=mid+1;
  148. else R=mid-1;
  149. }
  150. cout<<ans<<"\n";
  151. } else
  152. if(opt==3) {
  153. int pos=read(),k=read();
  154. modify(pos,k,1);
  155. w[pos]=k;
  156. } else
  157. if(opt==4) {
  158. int l=read(),r=read(),k=read();
  159. cout<<qq(l,r,k,1)<<"\n";
  160. } else
  161. if(opt==5) {
  162. int l=read(),r=read(),k=read();
  163. cout<<hj(l,r,k,1)<<"\n";
  164. }
  165. }
  166. return 0;
  167. }

P3380 【模板】二逼平衡树(树套树)的更多相关文章

  1. bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1807  Solved: 772[Submit][Stat ...

  2. bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description ...

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

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

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

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

  5. BZOJ 3196 Tyvj 1730 二逼平衡树:线段树套splay

    传送门 题意 给你一个长度为 $ n $ 有序数列 $ a $ ,进行 $ m $ 次操作,操作有如下几种: 查询 $ k $ 在区间 $ [l,r] $ 内的排名 查询区间 $ [l,r] $ 内排 ...

  6. [BZOJ3196] [Tyvj1730] 二逼平衡树(线段树 套 Splay)

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

  7. bzoj 3196 Tyvj 1730 二逼平衡树【线段树 套 splay】

    四舍五入就是个暴力. 对于线段树的每个区间都开一棵按权值排序的splay 对于第二个操作,二分一下,每次查询mid的排名,复杂度 $ O(nlog(n)^{3}) $ 其余的操作都是$ O(nlog( ...

  8. P3380 【模板】二逼平衡树(树套树)(线段树套平衡树)

    P3380 [模板]二逼平衡树(树套树) 前置芝士 P3369 [模板]普通平衡树 线段树套平衡树 这里写的是线段树+splay(不吸氧竟然卡过了) 对线段树的每个节点都维护一颗平衡树 每次把给定区间 ...

  9. 洛谷P3380 【模板】二逼平衡树(树套树)(线段树+树状数组)

    P3380 [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数 ...

  10. 洛谷 P3380 【模板】二逼平衡树(树套树)-线段树套splay

    P3380 [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数 ...

随机推荐

  1. FutureTask demo

    package com.xinwei.order.entity; import java.util.concurrent.ExecutorService; import java.util.concu ...

  2. Oracle表空间管理相关

    以下以我自己的测试环境举例: 1.表空间的 block_size 为 8192字节,即8KBytes.从数据字典中查到 max_size 为 2147483645,即约为15.9TBytes. 2.在 ...

  3. opencv的安装及填坑

    opencv的配置方式: https://blog.csdn.net/cocoaqin/article/details/78163171 输入Python时候报错: ERROR: ld.so: obj ...

  4. org.joda.time.DateTime 日期格式

    最近一直在使用Java,偶尔一次遇到日期(util)的格式转换,心里还是规矩的写着记忆里面的代码,但是在自己测试的时候发现不正确,具体看了下代码,发现这里使用jota的方式编写,顺道查了一下,做了笔记 ...

  5. python 数据较大 性能分析

    前提:若有一个几百M的文件需要解析,某个函数需要运行很多次(几千次),需要考虑性能问题 性能分析模块:cProfile 使用方法:cProfile.run("func()"),其中 ...

  6. Acperience (英语阅读 + 数学推导)

    #include<bits/stdc++.h> using namespace std; int main(){ int T,n,m;scanf("%d",&T ...

  7. django models数据库操作

    一.数据库操作 1.创建model表         基本结构 1 2 3 4 5 6 from django.db import models     class userinfo(models.M ...

  8. JAVA基础1---Object类解析

    1.Object简介 众所周知,Object类是Java所有类的万类之源,所有Java类都是继承之Object类,而默认就直接忽略了extends Object这段代码. 2.Object类的源码 话 ...

  9. js中的children实时获取子元素

    先看下面一个小例子的结果 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...

  10. JS报错修改日记(1):Uncaught ReferenceError: showQRcode is not defined

    为了加一个查看二维码的功能,如: //页面内按钮 <a class="manipulate-btn" href="#" onclick="sho ...