题意

您需要写一种数据结构,来维护一个序列,其中需要提供以下操作(对于各个以往的历史版本):

  1. 在第 pp 个数后插入数 xx 。
  2. 删除第 pp 个数。
  3. 翻转区间 [l,r][l,r],例如原序列是 {5,4,3,2,1}{5,4,3,2,1},翻转区间 [2,4][2,4] 后,结果是 {5,2,3,4,1}{5,2,3,4,1}。
  4. 查询区间 [l,r][l,r] 中所有数的和。

和原本平衡树不同的一点是,每一次的任何操作都是基于某一个历史版本,同时生成一个新的版本(操作 44 即保持原版本无变化),新版本即编号为此次操作的序号。

本题强制在线。

分析

函数式Treap实现。

时空复杂度\(O(n \log n)\)

代码

  1. // luogu-judger-enable-o2
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<cstdlib>
  5. #include<cmath>
  6. #include<set>
  7. #include<map>
  8. #include<queue>
  9. #include<stack>
  10. #include<algorithm>
  11. #include<bitset>
  12. #include<cassert>
  13. #include<ctime>
  14. #include<cstring>
  15. #define rg register
  16. #define il inline
  17. #define co const
  18. template<class T>il T read()
  19. {
  20. rg T data=0;
  21. rg int w=1;
  22. rg char ch=getchar();
  23. while(!isdigit(ch))
  24. {
  25. if(ch=='-')
  26. w=-1;
  27. ch=getchar();
  28. }
  29. while(isdigit(ch))
  30. {
  31. data=data*10+ch-'0';
  32. ch=getchar();
  33. }
  34. return data*w;
  35. }
  36. template<class T>T read(T&x)
  37. {
  38. return x=read<T>();
  39. }
  40. typedef long long ll;
  41. co int N=2e5+7;
  42. int tot;
  43. int root[N];
  44. int can[N],cantop;
  45. namespace T
  46. {
  47. using std::swap;
  48. int ch[N<<6][2],siz[N<<6];
  49. int pri[N<<6],val[N<<6];
  50. ll sum[N<<6];
  51. bool rev[N<<6];
  52. int newnode(int v=0)
  53. {
  54. int x=cantop?can[cantop--]:++tot;
  55. ch[x][0]=ch[x][1]=0,siz[x]=1;
  56. pri[x]=rand()<<15|rand(),val[x]=sum[x]=v;
  57. rev[x]=0;
  58. return x;
  59. }
  60. int clone(int y)
  61. {
  62. int x=cantop?can[cantop--]:++tot;
  63. ch[x][0]=ch[y][0],ch[x][1]=ch[y][1],siz[x]=siz[y];
  64. pri[x]=pri[y],val[x]=val[y],sum[x]=sum[y];
  65. rev[x]=rev[y];
  66. return x;
  67. }
  68. void pushup(int x)
  69. {
  70. siz[x]=siz[ch[x][0]]+1+siz[ch[x][1]];
  71. sum[x]=sum[ch[x][0]]+val[x]+sum[ch[x][1]];
  72. }
  73. void pushdown(int x)
  74. {
  75. if(rev[x])
  76. {
  77. swap(ch[x][0],ch[x][1]);
  78. if(ch[x][0])
  79. {
  80. ch[x][0]=clone(ch[x][0]);
  81. rev[ch[x][0]]^=1;
  82. }
  83. if(ch[x][1])
  84. {
  85. ch[x][1]=clone(ch[x][1]);
  86. rev[ch[x][1]]^=1;
  87. }
  88. rev[x]=0;
  89. }
  90. }
  91. void split(int x,int k,int&l,int&r)
  92. {
  93. if(!x)
  94. {
  95. l=r=0;
  96. return;
  97. }
  98. pushdown(x);
  99. if(k<=siz[ch[x][0]])
  100. {
  101. r=clone(x);
  102. split(ch[r][0],k,l,ch[r][0]);
  103. pushup(r);
  104. }
  105. else
  106. {
  107. l=clone(x);
  108. split(ch[l][1],k-siz[ch[x][0]]-1,ch[l][1],r);
  109. pushup(l);
  110. }
  111. }
  112. int merge(int x,int y)
  113. {
  114. if(!x||!y)
  115. return x+y;
  116. if(pri[x]<pri[y])
  117. {
  118. pushdown(y);
  119. ch[y][0]=merge(x,ch[y][0]);
  120. pushup(y);
  121. return y;
  122. }
  123. else
  124. {
  125. pushdown(x);
  126. ch[x][1]=merge(ch[x][1],y);
  127. pushup(x);
  128. return x;
  129. }
  130. }
  131. void insert(int&rt,int k,int v)
  132. {
  133. int x,y;
  134. split(rt,k,x,y);
  135. rt=merge(x,merge(newnode(v),y));
  136. }
  137. void erase(int&rt,int p)
  138. {
  139. int x,y,z;
  140. split(rt,p,x,z);
  141. split(x,p-1,x,y);
  142. can[++cantop]=y;
  143. rt=merge(x,z);
  144. }
  145. void reverse(int&rt,int l,int r)
  146. {
  147. int x,y,z;
  148. split(rt,r,x,z);
  149. split(x,l-1,x,y);
  150. rev[y]^=1;
  151. rt=merge(x,merge(y,z));
  152. }
  153. ll query(int&rt,int l,int r)
  154. {
  155. int x,y,z;
  156. split(rt,r,x,z);
  157. split(x,l-1,x,y);
  158. ll ans=sum[y];
  159. rt=merge(x,merge(y,z));
  160. return ans;
  161. }
  162. }
  163. using namespace T;
  164. using namespace std;
  165. int main()
  166. {
  167. // freopen(".in","r",stdin);
  168. // freopen(".out","w",stdout);
  169. int n=read<int>();
  170. ll lastans=0;
  171. for(int i=1;i<=n;++i)
  172. {
  173. int v,q;
  174. read(v),read(q);
  175. root[i]=root[v];
  176. if(q==1)
  177. {
  178. int p,x;
  179. read(p),read(x);
  180. p^=lastans,x^=lastans;
  181. insert(root[i],p,x);
  182. }
  183. else if(q==2)
  184. {
  185. int p;
  186. read(p);
  187. p^=lastans;
  188. erase(root[i],p);
  189. }
  190. else if(q==3)
  191. {
  192. int l,r;
  193. read(l),read(r);
  194. l^=lastans,r^=lastans;
  195. reverse(root[i],l,r);
  196. }
  197. else
  198. {
  199. int l,r;
  200. read(l),read(r);
  201. l^=lastans,r^=lastans;
  202. printf("%lld\n",lastans=query(root[i],l,r));
  203. }
  204. }
  205. return 0;
  206. }

LG5055 【模板】可持久化文艺平衡树的更多相关文章

  1. 【LG5055】可持久化文艺平衡树

    [LG5055]可持久化文艺平衡树 题面 洛谷 题解 终于不可以用\(Trie\)水了... 和普通的\(FHQ\;treap\)差不多 注意一下\(pushdown\).\(split\)要新开节点 ...

  2. P5055 【模板】可持久化文艺平衡树 可持久化fhqtreap

    P5055 [模板]可持久化文艺平衡树 链接 luogu 思路 可持久化fhq-treap套一套就行了,pushdown和split都要可持久化,但merge不用可持久.以前以为很难一直没看,就是个板 ...

  3. 洛谷P5055 可持久化文艺平衡树 (可持久化treap)

    题目链接 文艺平衡树的可持久化版,可以使用treap实现. 作为序列使用的treap相对splay的优点如下: 1.代码短 2.容易实现可持久化 3.边界处理方便(splay常常需要在左右两端加上保护 ...

  4. 【模板】可持久化文艺平衡树-可持久化treap

    题目链接 题意 对于各个以往的历史版本实现以下操作: 在第 p 个数后插入数 x . 删除第 p 个数. 翻转区间 [l,r],例如原序列是 \(\{5,4,3,2,1\}\),翻转区间 [2,4] ...

  5. Luogu5055 【模板】可持久化文艺平衡树(fhq-treap)

    注意下传标记时也需要新建节点.空间开的尽量大. #include<iostream> #include<cstdio> #include<cmath> #inclu ...

  6. 洛谷P5055 【模板】可持久化文艺平衡树(FHQ Treap)

    题面 传送门 题解 日常敲板子.jpg //minamoto #include<bits/stdc++.h> #define R register #define inline __inl ...

  7. luoguP5055 【模板】可持久化文艺平衡树 可持久化非旋转treap

    好题. Code: #include<bits/stdc++.h> using namespace std; #define setIO(s) freopen(s".in&quo ...

  8. SLT学习——leafes tree扩展 【文艺平衡树】

    这是一个全新的数据结构 md,别看这篇文章了,这篇已经废了. 百折不饶,再交一次,更新复杂度证明 这里是HYF,蒟蒻一只,最近因某些原因开始学数据结构了,然后就写了这篇题解. 下面给大家介绍一个全新的 ...

  9. 洛谷 P3391 【模板】文艺平衡树

    题目背景 这是一道经典的Splay模板题--文艺平衡树. 题目描述 您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4 ...

随机推荐

  1. c++的格式控制

    1: 每个iostream对象维持一个控制IO格式化细节的格式状态.标准库定义了一组操纵符来修改对象的格式状态.所谓操纵符是可用作输入或输出操作符的函数或对象.iostream和iomanip头文件中 ...

  2. React-Native 常用组件学习资料链接

    以下链接是自己开发RN工程时参考的一些不错的资料,给喜欢学习的朋友分享以下. React-Native组件用法详解之ListViewhttp://www.jianshu.com/p/1293bb8ac ...

  3. 用WAR的方式部署SpringBoot项目

    接SpringBoot 快速入门(Eclipse) 步骤一:部署方式 Springboot 和 web 应用程序不一样,其本质上是一个 Java 应用程序,那么又如何部署呢? 通常来说,Springb ...

  4. 分分享知识-快乐自己: @Component注解的使用

    @controller 控制器(注入服务) 用于标注控制层,相当于struts中的action层 @service 服务(注入dao) 用于标注服务层,主要用来进行业务的逻辑处理 @repositor ...

  5. telnet: connect to address ::1: connect refused [centos, linux]

    在我测试邮件服务器时, 使用 telnet localhost 25 出现如下的提示: Trying::1... telnet: connect to address ::1:Connection r ...

  6. Eclipse Android 代码自动提示功能

    Eclipse Android 代码自动提示功能 Eclipse for android 实现代码自动提示智能提示功能,介绍 Eclipse for android 编辑器中实现两种主要文件 java ...

  7. jQuery对select操作

    (转自:http://www.cnblogs.com/as285996985/articles/1535014.html) //遍历option和添加.移除optionfunction changeS ...

  8. Visual Studio 调试技巧:10 篇热文汇总

    本文精选了 DotNet  2017年11月份的10篇热门文章.其中有技术分享.技术资源. 注:以下文章,点击标题即可阅读 <Visual Studio的调试技巧 > 调试技巧是衡量程序员 ...

  9. win8 商店应用 设计风格原则

    共八条: 1,突出内容(数据). a,仅在屏幕上保留最相关的元素:移除线条.框和不必要的图形效果:限制屏幕上持久显示的导航框,如选项卡. b,交互尽量直接在内容上,直接控制内容来完成操作,而不是使用控 ...

  10. react-hooks: custom hooks

    memberEntitiy: export interface MemberEntity { id: number; name: string; code: string; } const useMe ...