学了半天平衡树,选择了一道题来写一写,发现题目是裸的splay模板,但是还是写不好,这个的精髓之处在于在数列的某一个位置加入一个数列,类似于treap里面的merge,然后还学到了题解里面的的回收空间做法,利用时间换取空间也是一种非常不错的做法,由于题目中有区间翻转的操作,所以只能用splay来写,然后对于一些区间最大值和区间最大子序列的询问我们可以用类似于线段树的合并操作来维护,总的来说这是一道对于树形数据结构非常好的运用的题目。——by VANE

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int inf=0x3f3f3f3f;
  4. const int N=1e6+;
  5. int n,m,rt,cnt;
  6. int a[N],id[N],fa[N],c[N][];
  7. int sum[N],sz[N],v[N],mx[N],lx[N],rx[N];
  8. bool tag[N],rev[N];
  9. queue<int> q;
  10. inline int read()
  11. {
  12. int x=,f=;char ch=getchar();
  13. while(ch<''||ch>'') {if(ch=='-') f=-f; ch=getchar();}
  14. while(ch>=''&&ch<='') {x=x*+ch-'';ch=getchar();}
  15. return x*f;
  16. }
  17. inline void pushup(int x)
  18. {
  19. int l=c[x][],r=c[x][];
  20. sum[x]=sum[l]+sum[r]+v[x];
  21. sz[x]=sz[l]+sz[r]+;
  22. mx[x]=max(mx[l],max(mx[r],rx[l]+v[x]+lx[r]));
  23. lx[x]=max(lx[l],sum[l]+v[x]+lx[r]);
  24. rx[x]=max(rx[r],sum[r]+v[x]+rx[l]);
  25. }
  26. inline void pushdown(int x)
  27. {
  28. int l=c[x][],r=c[x][];
  29. if(tag[x])
  30. {
  31. rev[x]=tag[x]=;
  32. if(l) tag[l]=,v[l]=v[x],sum[l]=v[x]*sz[l];
  33. if(r) tag[r]=,v[r]=v[x],sum[r]=v[x]*sz[r];
  34. if(v[x]>=)
  35. {
  36. if(l) lx[l]=rx[l]=mx[l]=sum[l];
  37. if(r) lx[r]=rx[r]=mx[r]=sum[r];
  38. }
  39. else
  40. {
  41. if(l) lx[l]=rx[l]=,mx[l]=v[x];
  42. if(r) lx[r]=rx[r]=,mx[r]=v[x];
  43. }
  44. }
  45. if(rev[x])
  46. {
  47. rev[x]=;rev[l]^=;rev[r]^=;
  48. swap(lx[l],rx[l]);swap(lx[r],rx[r]);
  49. swap(c[l][],c[l][]);swap(c[r][],c[r][]);
  50. }
  51. }
  52. inline void rotate(int x,int &k)
  53. {
  54. int y=fa[x],z=fa[y],l=(c[y][]==x),r=l^;
  55. if(y==k) k=x;else c[z][c[z][]==y]=x;
  56. fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
  57. c[y][l]=c[x][r];c[x][r]=y;
  58. pushup(y);pushup(x);
  59. }
  60. inline void splay(int x,int &k)
  61. {
  62. while(x!=k)
  63. {
  64. int y=fa[x],z=fa[y];
  65. if(y!=k)
  66. {
  67. if(c[z][]==y ^ c[y][]==x) rotate(x,k);
  68. else rotate(y,k);
  69. }
  70. rotate(x,k);
  71. }
  72. }
  73. inline int find(int x,int rk)
  74. {
  75. pushdown(x);
  76. int l=c[x][],r=c[x][];
  77. if(sz[l]+==rk) return x;
  78. if(sz[l]>=rk) return find(l,rk);
  79. return find(r,rk-sz[l]-);
  80. }
  81. inline void recycle(int x)
  82. {
  83. int &l=c[x][],&r=c[x][];
  84. if(l) recycle(l);
  85. if(r) recycle(r);
  86. q.push(x);
  87. fa[x]=l=r=tag[x]=rev[x]=;
  88. }
  89. inline int split(int k,int tot)
  90. {
  91. int x=find(rt,k),y=find(rt,k+tot+);
  92. splay(x,rt);splay(y,c[x][]);
  93. return c[y][];
  94. }
  95. inline void query(int k,int tot)
  96. {
  97. int x=split(k,tot);
  98. printf("%d\n",sum[x]);
  99. }
  100. inline void modify(int k,int tot,int val)
  101. {
  102. int x=split(k,tot),y=fa[x];
  103. v[x]=val;tag[x]=;sum[x]=sz[x]*val;
  104. if(val>=) lx[x]=rx[x]=mx[x]=sum[x];
  105. else lx[x]=rx[x]=,mx[x]=val;
  106. pushup(y);pushup(fa[y]);
  107. }
  108. inline void rever (int k,int tot)
  109. {
  110. int x=split(k,tot),y=fa[x];
  111. if(!tag[x])
  112. {
  113. rev[x]^=;
  114. swap(c[x][],c[x][]);
  115. swap(lx[x],rx[x]);
  116. pushup(y);pushup(fa[y]);
  117. }
  118. }
  119. inline void erase(int k,int tot)
  120. {
  121. int x=split(k,tot),y=fa[x];
  122. recycle(x);c[y][]=;
  123. pushup(y);pushup(fa[y]);
  124. }
  125. inline void build(int l,int r,int f)
  126. {
  127. int mid=l+r>>,now=id[mid],pre=id[f];
  128. if(l==r)
  129. {
  130. mx[now]=sum[now]=a[l];
  131. lx[now]=rx[now]=max(a[l],);
  132. sz[now]=;
  133. }
  134. if(l<mid) build(l,mid-,mid);
  135. if(mid<r) build(mid+,r,mid);
  136. v[now]=a[mid];fa[now]=pre;
  137. pushup(now);
  138. c[pre][mid>=f]=now;
  139. }
  140. inline void insert(int k,int tot)
  141. {
  142. for(int i=;i<=tot;++i) a[i]=read();
  143. for(int i=;i<=tot;++i)
  144. {
  145. if(!q.empty()) id[i]=q.front(),q.pop();
  146. else id[i]=++cnt;
  147. }
  148. build(,tot,);
  149. int z=id[+tot>>];
  150. int x=find(rt,k+),y=find(rt,k+);
  151. splay(x,rt);splay(y,c[x][]);
  152. fa[z]=y;c[y][]=z;
  153. pushup(y);pushup(x);
  154. }
  155. int main()
  156. {
  157. n=read();m=read();
  158. mx[]=a[]=a[n+]=-inf;
  159. for(int i=;i<=n;++i) a[i+]=read();
  160. for(int i=;i<=n+;++i) id[i]=i;
  161. build(,n+,);
  162. rt=n+>>;cnt=n+;
  163. int k,tot,val;char ch[];
  164. while(m--)
  165. {
  166. scanf("%s",ch);
  167. if(ch[]!='M'||ch[]!='X') k=read(),tot=read();
  168. if(ch[]=='I') insert(k,tot);
  169. if(ch[]=='D') erase(k,tot);
  170. if(ch[]=='M')
  171. {
  172. if(ch[]=='X') printf("%d\n",mx[rt]);
  173. else val=read(),modify(k,tot,val);
  174. }
  175. if(ch[]=='R') rever(k,tot);
  176. if(ch[]=='G') query(k,tot);
  177. }
  178. }

NOI2005 维护数列(splay)的更多相关文章

  1. P2042 [NOI2005]维护数列 && Splay区间操作(四)

    到这里 \(A\) 了这题, \(Splay\) 就能算入好门了吧. 今天是个特殊的日子, \(NOI\) 出成绩, 大佬 \(Cu\) 不敢相信这一切这么快, 一下子机房就只剩我和 \(zrs\) ...

  2. 洛谷 P2042 [NOI2005]维护数列-Splay(插入 删除 修改 翻转 求和 最大的子序列)

    因为要讲座,随便写一下,等讲完有时间好好写一篇splay的博客. 先直接上题目然后贴代码,具体讲解都写代码里了. 参考的博客等的链接都贴代码里了,有空再好好写. P2042 [NOI2005]维护数列 ...

  3. P2042 [NOI2005]维护数列[splay或非旋treap·毒瘤题]

    P2042 [NOI2005]维护数列 数列区间和,最大子列和(必须不为空),支持翻转.修改值.插入删除. 练码力的题,很毒瘤.个人因为太菜了,对splay极其生疏,犯了大量错误,在此记录,望以后一定 ...

  4. 洛谷.2042.[NOI2005]维护数列(Splay)

    题目链接 2017.12.24 第一次写: 时间: 2316ms (1268ms) 空间: 19.42MB (19.5MB)(O2) 注:洛谷测的时间浮动比较大 /* 插入一段数:将这些数先单独建一棵 ...

  5. BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay)

    手动博客搬家: 本文发表于20180825 00:34:49, 原地址https://blog.csdn.net/suncongbo/article/details/82027387 题目链接: (l ...

  6. 数据结构(Splay平衡树):COGS 339. [NOI2005] 维护数列

    339. [NOI2005] 维护数列 时间限制:3 s   内存限制:256 MB [问题描述] 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际 ...

  7. [NOI2005]维护数列(区间splay)

    [NOI2005]维护数列(luogu) 打这玩意儿真是要了我的老命 Description 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文 ...

  8. [NOI2005] 维护数列

    [NOI2005] 维护数列 题目 传送门 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 操作编号 输入文件中的格式 说明 1 ...

  9. Luogu P2042 [NOI2005]维护数列(平衡树)

    P2042 [NOI2005]维护数列 题意 题目描述 请写一个程序,要求维护一个数列,支持以下\(6\)种操作:(请注意,格式栏中的下划线'_'表示实际输入文件中的空格) 输入输出格式 输入格式: ...

随机推荐

  1. 【BZOJ】2142 礼物

    [算法]中国剩余定理 [题意]给定n件物品分给m个人,每人分到wi件,求方案数%p.p不一定是素数. [题解] 首先考虑n全排列然后按wi划分成m份,然后对于每份内都是全排列,除以wi!消除标号影响, ...

  2. MongoDB中的基础概念:Databases、Collections、Documents

    MongoDB以BSON格式的文档(Documents)形式存储.Databases中包含集合(Collections),集合(Collections)中存储文档(Documents). BSON是一 ...

  3. F - Warm up HDU - 4612 tarjan缩点 + 树的直径 + 对tajan的再次理解

    题目链接:https://vjudge.net/contest/67418#problem/F 题目大意:给你一个图,让你加一条边,使得原图中的桥尽可能的小.(谢谢梁学长的帮忙) 我对重边,tarja ...

  4. 深入理解Spring系列之一:开篇

    转载 https://mp.weixin.qq.com/s?__biz=MzI0NjUxNTY5Nw==&mid=2247483810&idx=1&sn=a2df14fdb63 ...

  5. WPF之DataGrid--列的前台及后台实现

    一.前台实现 在xaml里可以很轻松地实现一个如下图所示的DataGrid <StackPanel> <ComboBox Width="50" Horizonta ...

  6. ios 不支持iframe 解决方案

    在iframe外层在包一层,通过appendChild()把内容增加到容器中,完整代码如下: @section Css { <link href="@ViewHelper.Conten ...

  7. centos 6.5配置ftp服务器,亲测可用

    设置开机启动 1 chkconfig vsftpd on 启动服务 1 /sbin/service vsftpd start 配置FTP用户组/用户以及相应权限 添加用户组 1 groupadd ft ...

  8. angular项目中使用angular-material2

    Step 1: Install Angular Material and Angular CDK npm install --save @angular/material @angular/cdk n ...

  9. tftp 开发板ping不通PC机

    开发板:JZ2440(天下2440开发板是一家) 当进入uboot界面时:输入命令print则显示: 将PC端的IP设置为192.168.1.11 在开发板上ping   192.168.1.11,若 ...

  10. Python学习笔记——迭代器和生成器

    1.手动遍历迭代器 使用next函数,并捕获StopIteration异常. def manual_iter(): with open('./test.py') as f: try: while Tr ...