我写的是线段树套splay,网上很多人写的都是套treap,然而本蒟蒻并不会treap

奉上sth神犇的模板:

  1. //bzoj3196 二逼平衡树,支持修改某个点的值,查询区间第k小值,查询区间某个值排名,查询区间某个值值前驱、后继。查询第k小值是log^3(n)的,其他都是log^2(n)的
  2. #include <cstdio>
  3. using namespace std;
  4. const int maxn=,inf=;
  5. int a[maxn],f[maxn],sum[maxn],num[maxn],n,m,c[],root[],left,right,tot,son[maxn][];
  6. int mmin(int x,int y)
  7. {
  8. if (x<y) return x;
  9. return y;
  10. }
  11. int mmax(int x,int y)
  12. {
  13. if (x>y) return x;
  14. return y;
  15. }
  16. void rotate(int x,int w)
  17. {
  18. int y=f[x];
  19. if (f[y]) if (y==son[f[y]][]) son[f[y]][]=x; else son[f[y]][]=x;
  20. f[x]=f[y];
  21. if (son[x][w]) f[son[x][w]]=y;
  22. son[y][-w]=son[x][w];
  23. f[y]=x;
  24. son[x][w]=y;
  25. sum[y]=sum[son[y][]]+sum[son[y][]]+num[y];
  26. }
  27. void splay(int r,int x,int w)
  28. {
  29. int y;
  30. while (f[x]!=w)
  31. {
  32. y=f[x];
  33. if (f[y]==w) if (x==son[y][]) rotate(x,); else rotate(x,);
  34. else if (y==son[f[y]][]) if (x==son[y][]) {rotate(y,); rotate(x,); } else {rotate(x,); rotate(x,);}
  35. else if (x==son[y][]) {rotate(x,); rotate(x,);} else {rotate(y,); rotate(x,);}
  36. }
  37. sum[x]=sum[son[x][]]+sum[son[x][]]+num[x];
  38. if (w==) root[r]=x;
  39. }
  40. void insert(int r,int value)
  41. {
  42. int x=root[r];
  43. if (x==)
  44. {
  45. a[++tot]=value;
  46. num[tot]=sum[tot]=;
  47. root[r]=tot;
  48. return;
  49. }
  50. while (a[x]!=value)
  51. if (a[x]>value) {if (son[x][]) x=son[x][]; else break;}
  52. else {if (son[x][]) x=son[x][]; else break;}
  53. if (a[x]==value) {num[x]++; splay(r,x,); return;}
  54. a[++tot]=value;
  55. f[tot]=x;
  56. num[tot]=sum[tot]=;
  57. if (value<a[x]) son[x][]=tot; else son[x][]=tot;
  58. splay(r,tot,);
  59. }
  60. void del(int r,int value)
  61. {
  62. int x=root[r];
  63. while (a[x]!=value)
  64. if (a[x]>value) {if (son[x][]) x=son[x][]; else break;}
  65. else {if (son[x][]) x=son[x][]; else break;}
  66. splay(r,x,);
  67. if (num[x]>) {num[x]--; return;}
  68. if (!son[x][]) {root[r]=son[x][]; f[son[x][]]=; return;}
  69. if (!son[x][]) {root[r]=son[x][]; f[son[x][]]=; return;}
  70. int y=son[x][];
  71. while (son[y][]) y=son[y][];
  72. splay(r,y,x);
  73. son[y][]=son[x][];
  74. f[y]=;//一定记得f[y]=0
  75. f[son[y][]]=y;
  76. sum[y]=sum[son[y][]]+sum[son[y][]]+num[y];
  77. root[r]=y;
  78. }
  79. void build(int now,int l,int r)
  80. {
  81. //printf("now=%d l=%d r=%d\n",now,l,r);
  82. int i;
  83. for (i=l;i<=r;i++) insert(now,c[i]);//对每个线段树区间都建立一棵平衡树
  84. //print(now);
  85. if (l==r) return;
  86. int mid=(l+r)>>;
  87. i=now<<;
  88. build(i,l,mid);
  89. build(i+,mid+,r);
  90. }
  91. int find(int r,int value)
  92. {
  93. int x=root[r];
  94. while (a[x]!=value)
  95. if (a[x]>value) {if (son[x][]) x=son[x][]; else break;}
  96. else {if (son[x][]) x=son[x][]; else break;}
  97. splay(r,x,);
  98. return x;
  99. }
  100. int rank(int r,int k)
  101. {
  102. int x=find(r,k);
  103. if (a[x]>=k) return (sum[son[x][]]);
  104. return (sum[son[x][]]+num[x]);
  105. }
  106. int getrank(int now,int l,int r,int k)
  107. {
  108. if (l>=left&&r<=right) return (rank(now,k));
  109. int mid=(l+r)>>,w=now<<,ret=;
  110. if (left<=mid) ret=getrank(w,l,mid,k);
  111. if (right>mid) ret+=getrank(w+,mid+,r,k);
  112. return ret;
  113. }
  114. void change(int now,int l,int r,int pos,int value)
  115. {
  116. del(now,c[pos]);
  117. insert(now,value);
  118. if (l==r) return;
  119. int mid=(l+r)>>,w=now<<;
  120. if (pos<=mid) change(w,l,mid,pos,value); else change(w+,mid+,r,pos,value);
  121. }
  122. int ppre(int r,int value)
  123. {
  124. int x=root[r];
  125. while (a[x]!=value)
  126. if (a[x]>value) {if (son[x][]) x=son[x][]; else break;}
  127. else {if (son[x][]) x=son[x][]; else break;}
  128. if (a[x]==value)
  129. {
  130. splay(r,x,);
  131. if (!son[x][]) return ;
  132. x=son[x][];
  133. while (son[x][]) x=son[x][];
  134. return x;
  135. }
  136. while (f[x]&&a[x]>value) x=f[x];
  137. if (a[x]<value) return x;
  138. return ;
  139. }
  140. int ssucc(int r,int value)
  141. {
  142. int x=root[r];
  143. while (a[x]!=value)
  144. if (a[x]>value) {if (son[x][]) x=son[x][]; else break;}
  145. else {if (son[x][]) x=son[x][]; else break;}
  146. if (a[x]==value)
  147. {
  148. splay(r,x,);
  149. if (!son[x][]) return ;
  150. x=son[x][];
  151. while (son[x][]) x=son[x][];
  152. return x;
  153. }
  154. while (f[x]&&a[x]<value) x=f[x];
  155. if (a[x]>value) return x;
  156. return ;
  157. }
  158. int pre(int now,int l,int r,int value)
  159. {
  160. if (l>=left&&r<=right)
  161. {
  162. int x=ppre(now,value);
  163. if (a[x]<value) return a[x];
  164. x=find(now,);
  165. return -;
  166. }
  167. int mid=(l+r)>>,w=now<<,ret=-;
  168. if (left<=mid) ret=mmax(ret,pre(w,l,mid,value));
  169. if (right>mid) ret=mmax(ret,pre(w+,mid+,r,value));
  170. return ret;
  171. }
  172. int succ(int now,int l,int r,int value)
  173. {
  174. if (l>=left&&r<=right)
  175. {
  176. int x=ssucc(now,value);
  177. if (a[x]>value) return (a[x]);
  178. return inf;
  179. }
  180. int mid=(l+r)>>,w=now<<,ret=inf;
  181. if (left<=mid) ret=mmin(ret,succ(w,l,mid,value));
  182. if (right>mid) ret=mmin(ret,succ(w+,mid+,r,value));
  183. return ret;
  184. }
  185. int main()
  186. {
  187. scanf("%d%d",&n,&m);
  188. int i,kind,x,y,z,min,max,ans,mid;
  189. for (i=;i<=n;i++) scanf("%d",&c[i]);
  190. tot=;
  191. a[]=-,a[]=;
  192. build(,,n);
  193. for (i=;i<=m;i++)
  194. {
  195. scanf("%d%d%d",&kind,&x,&y);
  196. if (kind!=) scanf("%d",&z);
  197. if (kind==)
  198. {
  199. left=x,right=y;
  200. printf("%d\n",getrank(,,n,z)+);
  201. continue;
  202. }
  203. if (kind==)
  204. {
  205. left=x,right=y;
  206. min=,max=;
  207. while (min<=max)
  208. {
  209. mid=(min+max)>>;
  210. if (getrank(,,n,mid)<z) {ans=mid; min=mid+;} else max=mid-;
  211. }
  212. printf("%d\n",ans);
  213. continue;
  214. }
  215. if (kind==)
  216. {
  217. change(,,n,x,y);
  218. c[x]=y;
  219. continue;
  220. }
  221. if (kind==)
  222. {
  223. left=x,right=y;
  224. printf("%d\n",pre(,,n,z));
  225. continue;
  226. }
  227. left=x,right=y;
  228. printf("%d\n",succ(,,n,z));
  229. }
  230. return ;
  231. }

然后是我的AC code:

/*调了好久,一部分原因是做这道题时学长讲新课,没时间调这道题。今天终于调出来了,然后把三篇平衡树的博客一起写出来了。这个题的题解在上面sth神犇的模板里有,主要是那个二分k值是本题的特色。我这道题一直WA的原因是快速读入没有判断负号(╯‵□′)╯︵┻━┻*/

  1. #include<cstdio>
  2. #include<cctype>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. inline const int max(const int &a,const int &b){return a>b?a:b;}
  7. inline const int min(const int &a,const int &b){return a<b?a:b;}
  8. struct node{
  9. node();
  10. node *fa,*ch[];
  11. int sum,d;
  12. short pl(){return this==fa->ch[];}
  13. void count(){sum=ch[]->sum+ch[]->sum+;}
  14. }*null;
  15. node::node(){fa=ch[]=ch[]=null;sum=;}
  16. int data[],N,M;
  17. node *ROOT[<<];
  18. int getint(){char c;int fh=;while(!isdigit(c=getchar()))if (c=='-')fh=-;int a=c-'';while(isdigit(c=getchar()))a=a*+c-'';return a*fh;}
  19. namespace Splay{
  20. void Builda(){
  21. null=new node;
  22. *null=node();
  23. }
  24. void rotate(node *k,int rt){
  25. node *r=k->fa;
  26. if (k==null||r==null) return;
  27. int x=k->pl()^;
  28. r->ch[x^]=k->ch[x];
  29. r->ch[x^]->fa=r;
  30. if (r->fa==null) ROOT[rt]=k;
  31. else r->fa->ch[r->pl()]=k;
  32. k->fa=r->fa; r->fa=k;
  33. k->ch[x]=r;
  34. r->count(); k->count();
  35. }
  36. void splay(int rt,node *r,node *tar=null){
  37. for (;r->fa!=tar;rotate(r,rt))
  38. if (r->fa->fa!=tar)rotate(r->pl()==r->fa->pl()?r->fa:r,rt);
  39. }
  40. void insert(int rt,int x){
  41. node *r=ROOT[rt];
  42. if (ROOT[rt]==null){
  43. ROOT[rt]=new node;
  44. *ROOT[rt]=node();
  45. ROOT[rt]->d=x;
  46. ROOT[rt]->count();
  47. return;
  48. }
  49. while (){
  50. int c;
  51. if (x<r->d) c=;
  52. else c=;
  53. if (r->ch[c]==null){
  54. r->ch[c]=new node;
  55. *r->ch[c]=node();
  56. r->ch[c]->fa=r;
  57. r->ch[c]->d=x;
  58. splay(rt,r->ch[c]);
  59. return;
  60. }else r=r->ch[c];
  61. }
  62. }
  63. void build(int rt,int l,int r){
  64. ROOT[rt]=null;
  65. for(int i=l;i<=r;++i) insert(rt,data[i]);
  66. }
  67. node *kth(int rt,int x){
  68. node *r=ROOT[rt];
  69. while (r!=null){
  70. if (x<r->d) r=r->ch[];
  71. else if (x>r->d) r=r->ch[];
  72. else return r;
  73. }return r;
  74. }
  75. node *rightdown(node *r){
  76. while (r->ch[]!=null){
  77. r=r->ch[];
  78. }return r;
  79. }
  80. void deletee(int rt,int x){
  81. node *r=kth(rt,x);
  82. splay(rt,r);
  83. if ((r->ch[]==null)&&(r->ch[]==null)){
  84. ROOT[rt]=null;
  85. delete r;
  86. }else if (r->ch[]==null){
  87. r->ch[]->fa=null;
  88. ROOT[rt]=r->ch[];
  89. delete r;
  90. }else if (r->ch[]==null){
  91. r->ch[]->fa=null;
  92. ROOT[rt]=r->ch[];
  93. delete r;
  94. }else{
  95. splay(rt,rightdown(r->ch[]),ROOT[rt]);
  96. r->ch[]->ch[]=r->ch[];
  97. r->ch[]->fa=r->ch[];
  98. r->ch[]->fa=null;
  99. r->ch[]->count();
  100. ROOT[rt]=r->ch[];
  101. delete r;
  102. }
  103. }
  104. int predd(node *r,int x){
  105. if (r==null) return -;
  106. if (x<=r->d) return predd(r->ch[],x);
  107. else return max(r->d,predd(r->ch[],x));
  108. }
  109. int pross(node *r,int x){
  110. if (r==null) return 1E8+;
  111. if (x>=r->d) return pross(r->ch[],x);
  112. else return min(r->d,pross(r->ch[],x));
  113. }
  114. node *get1(node *r,int x){
  115. if (r==null) return null;
  116. if (x<r->d) return get1(r->ch[],x);
  117. if (x>r->d) return get1(r->ch[],x);
  118. node *rr=get1(r->ch[],x);
  119. if (rr!=null) return rr; else return r;
  120. }
  121. int quee1(int rt,int x){
  122. node *r=get1(ROOT[rt],x);
  123. if (r!=null){
  124. splay(rt,r);
  125. return r->ch[]->sum;
  126. }else{
  127. insert(rt,x);
  128. int anss=ROOT[rt]->ch[]->sum;
  129. deletee(rt,x);
  130. return anss;
  131. }
  132. }
  133. int quee2(int rt,int x){
  134. node *r=get1(ROOT[rt],x);
  135. if (r!=null){
  136. splay(rt,r);
  137. return r->ch[]->sum;
  138. }else{
  139. insert(rt,x);
  140. int anss=ROOT[rt]->ch[]->sum;
  141. deletee(rt,x);
  142. return anss;
  143. }
  144. }
  145. }
  146. void buildtree(int l,int r,int rt){
  147. Splay::build(rt,l,r);
  148. if (l==r) {Splay::build(rt,l,r);return;}
  149. int mid=(l+r)>>;
  150. buildtree(l,mid,rt<<);
  151. buildtree(mid+,r,rt<<|);
  152. }
  153. int que1(int L,int R,int k,int l,int r,int rt){
  154. if ((L<=l)&&(r<=R)) return Splay::quee1(rt,k);
  155. int mid=(l+r)>>,s=;
  156. if (L<=mid) s+=que1(L,R,k,l,mid,rt<<);
  157. if (R>mid) s+=que1(L,R,k,mid+,r,rt<<|);
  158. return s;
  159. }
  160. int que2(int L,int R,int k,int l,int r,int rt){
  161. if ((L<=l)&&(r<=R)) return Splay::quee2(rt,k);
  162. int mid=(l+r)>>,s=;
  163. if (L<=mid) s+=que2(L,R,k,l,mid,rt<<);
  164. if (R>mid) s+=que2(L,R,k,mid+,r,rt<<|);
  165. return s;
  166. }
  167. void que3(int pos,int k,int l,int r,int rt){
  168. if ((l<=pos)&&(pos<=r)){
  169. Splay::deletee(rt,data[pos]);
  170. Splay::insert(rt,k);
  171. }if (l==r) return; int mid=(l+r)>>;
  172. if (pos<=mid) que3(pos,k,l,mid,rt<<);
  173. if (pos>mid) que3(pos,k,mid+,r,rt<<|);
  174. }
  175. int que4(int L,int R,int k,int l,int r,int rt){
  176. if ((L<=l)&&(r<=R)) return Splay::predd(ROOT[rt],k);
  177. int mid=(l+r)>>,s=-;
  178. if (L<=mid) s=que4(L,R,k,l,mid,rt<<);
  179. if (R>mid) s=max(s,que4(L,R,k,mid+,r,rt<<|));
  180. return s;
  181. }
  182. int que5(int L,int R,int k,int l,int r,int rt){
  183. if ((L<=l)&&(r<=R)) return Splay::pross(ROOT[rt],k);
  184. int mid=(l+r)>>,s=1E8+;
  185. if (L<=mid) s=que5(L,R,k,l,mid,rt<<);
  186. if (R>mid) s=min(s,que5(L,R,k,mid+,r,rt<<|));
  187. return s;
  188. }
  189. int main(){
  190. Splay::Builda();
  191. N=getint();M=getint();
  192. for(int i=;i<=N;++i)data[i]=getint();
  193. buildtree(,N,);
  194. while (M){M--;
  195. int x=getint();
  196. switch (x){
  197. int l,r,k,pos,ans,left,right,mid;
  198. case :
  199. l=getint(),r=getint(),k=getint();
  200. printf("%d\n",que1(l,r,k,,N,)+);
  201. break;
  202. case :
  203. l=getint(),r=getint(),k=getint(),left=,right=1E8;
  204. while (left<=right){
  205. mid=(left+right)>>;
  206. if (que2(l,r,mid,,N,)+<=k) ans=mid,left=mid+;
  207. else right=mid-;
  208. }printf("%d\n",ans);
  209. break;
  210. case :
  211. pos=getint(),k=getint();
  212. que3(pos,k,,N,);
  213. data[pos]=k;
  214. break;
  215. case :
  216. l=getint(),r=getint(),k=getint();
  217. printf("%d\n",que4(l,r,k,,N,));
  218. break;
  219. case :
  220. l=getint(),r=getint(),k=getint();
  221. printf("%d\n",que5(l,r,k,,N,));
  222. break;
  223. }
  224. }
  225. return ;
  226. }

这样就可以了

【BZOJ 3196】二逼平衡树 线段树套splay 模板题的更多相关文章

  1. bzoj 3196二逼平衡树 线段树套平衡树

    比较裸的树套树,对于区间K值bz上有一道裸题,详见题解http://www.cnblogs.com/BLADEVIL/p/3455336.html(其实题解也不是很详细) //By BLADEVIL ...

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

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

  3. bzoj 3196 && luogu 3380 JoyOI 1730 二逼平衡树 (线段树套Treap)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 题面; 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Se ...

  4. BZOJ - 3196 Tyvj 1730 二逼平衡树 (线段树套treap)

    题目链接 区间线段树套treap,空间复杂度$O(nlogn)$,时间复杂度除了查询区间k大是$O(log^3n)$以外都是$O(log^2n)$的. (据说线段树套线段树.树状数组套线段树也能过?) ...

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

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

  6. bzoj3196 二逼平衡树——线段树套平衡树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 人生中第一棵树套树! 写了一个晚上,成功卡时 9000ms+ 过了! 很要注意数组的大 ...

  7. [bzoj3196]Tyvj 1730 二逼平衡树——线段树套平衡树

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

  8. 【bzoj3196】Tyvj 1730 二逼平衡树 线段树套Treap

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

  9. [bzoj3196][Tyvj 1730][二逼平衡树] (线段树套treap)

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

随机推荐

  1. 如何解决inline-block元素的空白间距

    早上在博客中有人提了这样一个问题:“li元素inline-block横向排列,出现了未知间隙”,我相信大家在写页面的时候都遇到过这样的情况吧. 我一般遇到这情况都会把li浮动起来,这样就没有间隙.但是 ...

  2. 谈谈自己对java的学习看法

    从明天起,开始整理java的基础知识,进行巩固学习. 今天呢,谈谈自己的一点想法.很多人不知道java怎么学,学什么,有的是直接在网上找一些视频来看,不懂的地方到处跑群里问,结果效果并不是太好,怎么办 ...

  3. AC日记——无线网络发射器选址 洛谷 P2038

    题目描述 随着智能手机的日益普及,人们对无线网的需求日益增大.某城市决定对城市内的公共场所覆盖无线网. 假设该城市的布局为由严格平行的129 条东西向街道和129 条南北向街道所形成的网格状,并且相邻 ...

  4. 开坑,Unix环境高级编程,转行之路又得缓缓了

    不要问我基础,我用了近6年的Linux系统,最早的版本可以追溯到Ubuntu 8.04,常用的命令 VIM基本上是没压力,遇到问题google 配置环境变量 网络环境也不在话下, C语法基本熟练,过去 ...

  5. f2fs源码解析(五) node管理结构梳理

    node是f2fs重要的管理结构, 它非常重要! 系统挂载完毕后, 会有一个f2fs_nm_info结构的node管理器来管理node的分配. f2fs_nm_info中最让人疑惑的是几颗基数树: s ...

  6. 第二章 时间控件(DateTime Picker)

    这家伙太懒了,碰到问题才写博文,嘿嘿. 好了进入正题,二话不说,先放地址: 中文:http://www.bootcss.com/p/bootstrap-datetimepicker/index.htm ...

  7. 【WPF】WPF通过RelativeSource绑定父控件的属性

    1.后台代码实现绑定父控件的属性 RelativeSource rs = new RelativeSource(RelativeSourceMode.FindAncestor); //设定为离自己控件 ...

  8. 【Asp.Net】Asp.Net CommandName作用

    数据绑定控件的模板中 CommandName 属性以下属性值会触发特定的事件: Cancel(取消) Delete(删除) Select(选择) Edit(编辑) Insert(插入) Update( ...

  9. C# 无边框窗体的最小化问题

    WinForm在窗体风格设置成None时无法最小化的问题.添加以下代码即可实现最小化: protected override CreateParams CreateParams { get { con ...

  10. Oracle异常处理,动态游标

    小例子,方便以后查阅. 包头需要声明:   type C_CURSOR is ref cursor; procedure visitcount(in_date number, out_code out ...