刚了一天的题终于切掉了,数据结构题的代码真**难调,这是我做过的第一道树套树题,做完后感觉对树套树都有阴影了......下面写一下做题记录.

  Portal Gun:[BZOJ3065]带插入区间k小值.

  这道题的题面其实都提醒怎么做了,维护区间k小值用值域线段树,但要维护一个插入操作,树状数组套主席树也用不了,那么这道题还剩下平衡树可以搞,那就上平衡树吧.

  我这里的做法,因为要维护序列的顺序,所以我这里用到替罪羊树套值域线段树:我们在替罪羊树的每个节点都套一颗值域线段树,记录以该节点为根的子树的值域的 size ,替罪羊树中我们维护每一个数在数列中的序号,在插入一个数时,就用它的值去更新插入时经过的所有点,就可以完成插入操作.至于修改操作,其实也就是插入操作,新值 size++ ,旧值 size-- .

  关于复杂度:对于每次插入,替罪羊树是 O(logn) ,插入值域线段树是 O(logn) ,复杂度为 O(log^2) .对于每次查询,替罪羊树找区间是 O(logn) , 查询值域线段树是 O(logn) ,复杂度为 O(log^2) ,替罪羊树重构复杂度均摊为 O(log^2) .

  

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #define maxn (70005)
  5. #define al 0.75
  6. #define il inline
  7. #define RG register
  8. using namespace std;
  9. il int gi(){ RG int x=0,q=1; RG char ch=getchar(); while( ( ch<'0' || ch>'9' ) && ch!='-' ) ch=getchar();
  10. if( ch=='-' ) q=-1,ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; }
  11. struct node{int l,r,size;}t[maxn*200];//值域线段树
  12. int n,m,ans,flag,root,cnt,Max=70000;
  13. int id[maxn],w[maxn],rt[maxn],ls[maxn],rs[maxn]; //替罪羊树
  14. int sta[maxn*100],top; //存回收节点
  15. il int newnode(){ if(!top) return ++cnt; else return sta[top--]; }
  16. il bool BALANCE(int x){
  17. return t[ rt[x] ].size*al>t[ rt[ls[x]] ].size
  18. && t[ rt[x] ].size*al>t[ rt[rs[x]] ].size;
  19. }
  20. il void recycle(int &x){
  21. if(!x) return ; sta[++top]=x;
  22. recycle(t[x].l),recycle(t[x].r);
  23. t[x].size=0,x=0;
  24. }
  25. il void insert(RG int &x,RG int l,RG int r,RG int val,RG int sum){ //线段树插入
  26. if(!x) x=newnode();
  27. if(l==r){ t[x].size+=sum; return ; }
  28. RG int mid=(l+r)>>1;
  29. if(val<=mid) insert( t[x].l,l,mid,val,sum );
  30. else insert( t[x].r,mid+1,r,val,sum );
  31. t[x].size=t[ t[x].l ].size+t[ t[x].r ].size;
  32. if(!t[x].size) recycle(x);
  33. }
  34. il void build(RG int &x,RG int l,RG int r){
  35. if(l>r) return ;
  36. if(l==r){ x=id[l]; insert(rt[x],0,Max,w[x],1); return ; }
  37. RG int mid=(l+r)>>1; x=id[mid];
  38. build(ls[x],l,mid-1); build(rs[x],mid+1,r);
  39. for(RG int i=l;i<=r;i++) insert(rt[x],0,Max,w[id[i]],1);
  40. }
  41. int cur[maxn*100],c_size;
  42. il void dfs(RG int &x){
  43. if(!x) return ; recycle(rt[x]);
  44. dfs(ls[x]); cur[++c_size]=x; dfs(rs[x]);
  45. x=0;
  46. }
  47. il void REBUILD(int &x){
  48. dfs(x);
  49. for(RG int i=1;i<=c_size;i++) id[i]=cur[i];
  50. build(x,1,c_size); c_size=0;
  51. }
  52. il void INSERT(RG int &x,RG int l,RG int val){
  53. if(!x){
  54. x=++n; w[x]=val;
  55. insert(rt[x],0,Max,val,1);
  56. return ;
  57. }
  58. insert( rt[x],0,Max,val,1 );
  59. int L=t[ rt[ ls[x] ] ].size;
  60. if(l<=L) INSERT(ls[x],l,val);
  61. else INSERT(rs[x],l-L-1,val);
  62. if(BALANCE(x)){ if(flag){
  63. if(ls[x]==flag) REBUILD(ls[x]);
  64. else REBUILD(rs[x]); flag=0;
  65. }
  66. }
  67. else{ flag=x; if(flag==root) REBUILD(root); }
  68. }
  69. il int modify(RG int x,RG int l,RG int val){
  70. insert(rt[x],0,Max,val,1); //插入新值
  71. int tt,L=t[ rt[ls[x]] ].size;
  72. if(l==L+1){ tt=w[x]; w[x]=val; }
  73. else if(l<=L) tt=modify(ls[x],l,val);
  74. else tt=modify(rs[x],l-L-1,val);
  75. insert(rt[x],0,Max,tt,-1); //删除原值
  76. return tt;
  77. }
  78. int tt[maxn*100],t_size,v[maxn*100],v_size;
  79. il void query(int k,int l,int r){
  80. int L=t[ rt[ ls[k] ] ].size,R=t[ rt[k] ].size;
  81. if(l==1 && r==R){ tt[++t_size]=rt[k]; return ; }
  82. if(l<=L+1 && r>=L+1) v[++v_size]=w[k];
  83. if(r<=L) query(ls[k],l,r);
  84. else if(l>L+1) query(rs[k],l-L-1,r-L-1);
  85. else{
  86. if(l<=L) query(ls[k],l,L);
  87. if(R>L+1) query(rs[k],1,r-L-1);
  88. }
  89. }
  90. il int QUERY(int L,int R,int k){
  91. query(root,L,R); k--;
  92. int l=0,r=Max;
  93. while(l<r){
  94. RG int mid=(l+r)>>1,sum=0;
  95. for(RG int i=1;i<=t_size;i++) sum+=t[ t[ tt[i] ].l ].size;
  96. for(RG int i=1;i<=v_size;i++) if(v[i]>=l && v[i]<=mid) sum++;
  97. if(k<sum){
  98. for(RG int i=1;i<=t_size;i++) tt[i]=t[ tt[i] ].l;
  99. r=mid;
  100. }
  101. else{
  102. for(RG int i=1;i<=t_size;i++) tt[i]=t[ tt[i] ].r;
  103. l=mid+1,k-=sum;
  104. }
  105. }
  106. t_size=0,v_size=0;
  107. return l;
  108. }
  109. il void init(){
  110. n=gi(); for(RG int i=1;i<=n;i++) w[i]=gi(),id[i]=i;
  111. build(root,1,n);
  112. }
  113. il void work(){
  114. m=gi(); char s[2]; int x,y,k;
  115. while(m--){
  116. scanf("%s",s);
  117. x=gi()^ans,y=gi()^ans;
  118. if(s[0]=='M') modify(root,x,y);
  119. if(s[0]=='I'){ flag=0; INSERT(root,x-1,y); }
  120. if(s[0]=='Q'){ k=gi()^ans;ans=QUERY(x,y,k);printf("%d\n",ans); }
  121. }
  122. }
  123. int main(){ init(); work(); return 0; }

  

  

[BZOJ3065]带插入区间K小值 解题报告 替罪羊树+值域线段树的更多相关文章

  1. 【bzoj3065】: 带插入区间K小值 详解——替罪羊套函数式线段树

    不得不说,做过最爽的树套树———— 由于有了区间操作,我们很容易把区间看成一棵平衡树,对他进行插入,那么外面一层就是平衡树了,这就与我们之前所见到的不同了.我们之前所见到的大多数是线段树套平衡树而此题 ...

  2. BZOJ3065 带插入区间K小值 || 洛谷P4278

    这是一道让我崩溃的题...... 然鹅洛谷上时限被改然后只有20分......好像所有人都被卡了(雾) 由于替罪羊树不是依靠旋转操作而是依靠暴力重构的方式维护树的平衡,所以我们可以考虑使用替罪羊树套区 ...

  3. 【函数式权值分块】【块状链表】bzoj3065 带插入区间K小值

    显然是块状链表的经典题.但是经典做法的复杂度是O(n*sqrt(n)*log^2(n))的,出题人明确说了会卡掉. 于是我们考虑每个块内记录前n个块的权值分块. 查询的时候差分什么的,复杂度就是O(n ...

  4. bzoj3065: 带插入区间K小值

    无聊来写了下 一开始发现树高是O(n)的,然后就MLE了,进去看了下发现没有重构! 看了半天发现调用错了函数 然后进去又发现不满足sz = ch[0]->sz + ch[1]->sz + ...

  5. 3065: 带插入区间K小值_树套树_替罪羊树_权值线段树

    经过周六一天,周一3个小时的晚自习,周二2个小时的疯狂debug,终于凭借自己切掉了这道树套树题. Code: #include <cstdio> #include <algorit ...

  6. 【BZOJ3065】带插入区间K小值 替罪羊树+权值线段树

    [BZOJ3065]带插入区间K小值 Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理 ...

  7. bzoj 3065: 带插入区间K小值 替罪羊树 && AC300

    3065: 带插入区间K小值 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 1062  Solved: 253[Submit][Status] Des ...

  8. 【题解】BZOJ 3065: 带插入区间K小值——替罪羊树套线段树

    题目传送门 题解 orz vfk的题解 3065: 带插入区间K小值 系列题解 一 二 三 四 惨 一开始用了一种空间常数很大的方法,每次重构的时候merge两颗线段树,然后无限RE(其实是MLE). ...

  9. BZOJ 3065 带插入区间K小值(sag套线段树)

    3065: 带插入区间K小值 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 4696  Solved: 1527[Submit][Status][Di ...

随机推荐

  1. WebGL2系列之实例数组(Instanced Arrays)

    实例化数组 实例化是一种只调用一次渲染函数却能绘制出很多物体的技术,它节省渲染一个物体时从CPU到GPU的通信时间.实例数组是这样的一个对象,使用它,可以把原来的的uniform变量转换成attrib ...

  2. vue 动画

    Vue 在插入.更新或者移除 DOM 时,提供多种不同方式的应用过渡效果.包括以下几种常见的方式: 在 CSS 过渡和动画中自动应用 class 可以配合使用第三方 CSS 动画库,如 Animate ...

  3. CHAPTER 25 The Greatest Show on Earth 第25章 地球上最壮观的演出

    CHAPTER 25 The Greatest Show on Earth 第25章 地球上最壮观的演出 Go for a walk in the countryside and you will f ...

  4. windows下在virtualbox中的Fuel Openstack 9.0 安装过程

    一.材料: 1.软件: virtualbox xshell(或putty,winscp) bootstrap.zip(580MB) mirrors(3.01GB) MirantisOpenStack- ...

  5. redis高级应用(集群搭建、集群分区原理、集群操作)

    文章主目录 Redis集群简介 Redis集群搭建 Redis集群分区原理 集群操作 参考文档 本文是redis学习系列的第四篇,前面我们学习了redis的数据结构和一些高级特性,点击下面链接可回看 ...

  6. Vue 入门之概念

    Vue 简介 Vue 是一个前端的双向绑定类的框架,发音[读音 /vjuː/, 类似于 [view].新的 Vue 版本参考了 React 的部分设计,当然也有自己独特的地方,比如 Vue 的单文件组 ...

  7. final发布视频展示博客

    Part One [探路者]选题展示视频链接: http://v.youku.com/v_show/id_XMzIxMDM2MTQ1Ng==.html?spm=a2h3j.8428770.341605 ...

  8. 软件工程第十周psp

    1.PSP表格 2.进度条 3.饼状图 4.折线图

  9. 信息安全系统设计基础_exp1

    北京电子科技学院(BESTI) 实     验    报     告 课程:信息安全系统设计基础 班级:1353 姓名:吴子怡.郑伟 学号:20135313.20135322 指导教师: 娄嘉鹏 实验 ...

  10. java程序设计课程实验报告3

    北京电子科技学院(BESTI) 实     验    报     告 课程:java程序设计    班级:1353  姓名:陈都  学号:20135328 成绩:             指导教师:娄 ...