http://www.lydsy.com/JudgeOnline/problem.php?id=1500 (题目链接)

题意

  要求维护数列,操作有区间删除,区间插入,区间反转,区间修改,区间求和,求最大连续子段。

Solution

  愿有生之年再也不写splay。代码模的hzwer。

  2017.3.24:upd了一下代码。

代码

  1. // baoj1500
  2. #include<algorithm>
  3. #include<iostream>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<cstdio>
  7. #include<cmath>
  8. #include<queue>
  9. #define LL long long
  10. #define inf (1ll<<30)
  11. #define Pi acos(-1.0)
  12. #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
  13. using namespace std;
  14. inline int gi() {
  15. int x=0,f=1;char ch=getchar();
  16. while (ch<'0' || ch>'9') {if (ch=='-') f=-1;ch=getchar();}
  17. while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
  18. return x*f;
  19. }
  20.  
  21. const int maxn=1000010;
  22. int a[maxn],fa[maxn],n,m,rt,sz;
  23. char ch[30];
  24. struct node {
  25. int lx,rx,mx,val,sum,size,son[2],rev,tag;
  26. int& operator [] (int x) {return son[x];}
  27. }tr[maxn];
  28. queue<int> q;
  29.  
  30. void pushup(int k) {
  31. int l=tr[k][0],r=tr[k][1];
  32. tr[k].size=tr[l].size+tr[r].size+1; //子树大小
  33. tr[k].sum=tr[l].sum+tr[r].sum+tr[k].val; //区间和
  34. tr[k].mx=max(tr[l].mx,tr[r].mx); //最大连续段
  35. tr[k].mx=max(tr[k].mx,tr[l].rx+tr[k].val+tr[r].lx);
  36. tr[k].lx=max(tr[l].lx,tr[l].sum+tr[k].val+tr[r].lx); //左端最大区间
  37. tr[k].rx=max(tr[r].rx,tr[r].sum+tr[k].val+tr[l].rx); //右端最大区间
  38. }
  39. void pushdown(int k) {
  40. int l=tr[k][0],r=tr[k][1];
  41. if (tr[k].tag) {
  42. tr[k].tag=tr[k].rev=0; //赋成同一个值,反不反转都一样
  43. if (l) tr[l].tag=1,tr[l].val=tr[k].val,tr[l].sum=tr[l].val*tr[l].size;
  44. if (r) tr[r].tag=1,tr[r].val=tr[k].val,tr[r].sum=tr[r].val*tr[r].size;
  45. if (tr[k].val>=0) {
  46. if (l) tr[l].lx=tr[l].rx=tr[l].mx=tr[l].sum;
  47. if (r) tr[r].lx=tr[r].rx=tr[r].mx=tr[r].sum;
  48. }
  49. else {
  50. if (l) tr[l].lx=tr[l].rx=0,tr[l].mx=tr[l].val;
  51. if (r) tr[r].lx=tr[r].rx=0,tr[r].mx=tr[r].val;
  52. }
  53. }
  54. if (tr[k].rev) {
  55. tr[k].rev^=1,tr[l].rev^=1,tr[r].rev^=1;
  56. swap(tr[l].lx,tr[l].rx),swap(tr[l][0],tr[l][1]);
  57. swap(tr[r].lx,tr[r].rx),swap(tr[r][0],tr[r][1]);
  58. }
  59. }
  60. void rotate(int x,int &k) {
  61. int y=fa[x],z=fa[y],l,r;
  62. l=tr[y][1]==x;r=l^1;
  63. if (y==k) k=x;
  64. else tr[z][tr[z][1]==y]=x;
  65. fa[tr[x][r]]=y;fa[y]=x;fa[x]=z;
  66. tr[y][l]=tr[x][r];tr[x][r]=y;
  67. pushup(y),pushup(x); //注意更新顺序
  68. }
  69. void splay(int x,int &k) {
  70. while (x!=k) {
  71. int y=fa[x],z=fa[y];
  72. if (y!=k) {
  73. if ((tr[y][0]==x) ^ (tr[z][0]==y)) rotate(x,k);
  74. else rotate(y,k);
  75. }
  76. rotate(x,k);
  77. }
  78. }
  79. int find(int k,int x) {
  80. pushdown(k);
  81. if (tr[tr[k][0]].size+1==x) return k;
  82. else if (x<=tr[tr[k][0]].size) return find(tr[k][0],x);
  83. else return find(tr[k][1],x-tr[tr[k][0]].size-1);
  84. }
  85. void recycle(int k) { //清空
  86. if (tr[k][0]) recycle(tr[k][0]);
  87. if (tr[k][1]) recycle(tr[k][1]);
  88. q.push(k);tr[k][0]=tr[k][1]=tr[k].tag=tr[k].rev=0; //节点回收入队,重复利用
  89. }
  90. int split(int l,int r) { //抠出区间
  91. int x=find(rt,l),y=find(rt,r+2);
  92. splay(x,rt),splay(y,tr[x][1]);
  93. return tr[y][0];
  94. }
  95. int query(int l,int r) {
  96. return tr[split(l,r)].sum;
  97. }
  98. void modify(int l,int r,int val) {
  99. int x=split(l,r),y=fa[x];
  100. tr[x].val=val;tr[x].tag=1;tr[x].sum=tr[x].size*val;
  101. if (val>=0) tr[x].lx=tr[x].rx=tr[x].mx=tr[x].sum;
  102. else tr[x].lx=tr[x].rx=0,tr[x].mx=val;
  103. pushup(y),pushup(fa[y]);
  104. }
  105. void reverse(int l,int r) {
  106. int x=split(l,r),y=fa[x];
  107. if (!tr[x].tag) {
  108. tr[x].rev^=1;
  109. swap(tr[x][0],tr[x][1]);
  110. swap(tr[x].lx,tr[x].rx);
  111. pushup(y),pushup(fa[y]);
  112. }
  113. }
  114. void erase(int l,int r) {
  115. int x=split(l,r),y=fa[x];
  116. recycle(x);tr[y][0]=0;
  117. pushup(y),pushup(fa[y]);
  118. }
  119. void build(int &k,int l,int r,int f) {
  120. int mid=(l+r)>>1;
  121. if (!q.empty()) k=q.front(),q.pop();else k=++sz;
  122. tr[k].sum=tr[k].val=a[mid];fa[k]=f;
  123. tr[k].lx=tr[k].rx=tr[k].mx=max(0,a[mid]);
  124. if (l<mid) build(tr[k][0],l,mid-1,k);
  125. if (r>mid) build(tr[k][1],mid+1,r,k);
  126. pushup(k);
  127. }
  128. void insert(int k,int tot) {
  129. for (int i=1;i<=tot;i++) scanf("%d",&a[i]);
  130. int x,y,z;
  131. build(z,1,tot,0);
  132. x=find(rt,k+1),y=find(rt,k+2); //因为有"哨兵",实际上是find k,k+1
  133. splay(x,rt),splay(y,tr[x][1]); //因为k,k+1,所以tr[y][0]为空
  134. fa[z]=y;tr[y][0]=z;pushup(y),pushup(x); //注意pushup的顺序
  135. }
  136. int main() {
  137. n=gi(),m=gi();
  138. tr[0].mx=a[1]=a[n+2]=-inf;
  139. for (int i=1;i<=n;i++) a[i+1]=gi();
  140. build(rt,1,n+2,0);
  141. while (m--) {
  142. int k,tot,val;scanf("%s",ch);
  143. if (ch[0]!='M' || ch[2]!='X') k=gi(),tot=gi();
  144. if (ch[0]=='I') insert(k,tot);
  145. else if (ch[0]=='D') erase(k,k+tot-1);
  146. else if (ch[0]=='M') {
  147. if (ch[2]=='X') printf("%d\n",tr[rt].mx);
  148. else scanf("%d",&val),modify(k,k+tot-1,val);
  149. }
  150. else if (ch[0]=='R') reverse(k,k+tot-1);
  151. else if (ch[0]=='G') printf("%d\n",query(k,k+tot-1));
  152. }
  153. return 0;
  154. }

  

【bzoj1500】 noi2005—维护数列的更多相关文章

  1. [您有新的未分配科技点] 无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MB Description Input 输入的第1 行包含两个数N 和M(M ≤20 ...

  2. [转载]无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )

    转自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182631.html 1500: [NOI2005]维修数列 Time Limit: 10 Sec  Mem ...

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

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

  4. [BZOJ1500][NOI2005]维修数列---解题报告

    Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...

  5. [NOI2005] 维护数列

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

  6. [BZOJ1500][NOI2005]维修数列 解题报告 Splay

    Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...

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

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

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

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

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

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

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

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

随机推荐

  1. PAT 1022. D进制的A+B (20)

    输入两个非负10进制整数A和B(<=230-1),输出A+B的D (1 < D <= 10)进制数. 输入格式: 输入在一行中依次给出3个整数A.B和D. 输出格式: 输出A+B的D ...

  2. JS 关闭 页面 浏览器 事件

    JS监听关闭浏览器事件关键字: js监听关闭浏览器事件Onunload与OnbeforeunloadOnunload,onbeforeunload都是在刷新或关闭时调用,可以在<script&g ...

  3. Html5 Egret游戏开发 成语大挑战(五)界面切换和数据处理

    经过前面的制作,使用Egret的Wing很快完成了开始界面和选关卡界面,下面通常来说就是游戏界面,但此时界面切换和关卡数据还没有准备好,这次讲解界面的切换和关卡数据的解析.前面多次修改了Main.ts ...

  4. android values目录的读取优先级

    android项目新建时会有一个values目录(高版本会增加values-v11,values-v14目录),该目录用于存放显示相的配置数据的定义文件,如strings.xml, style.xml ...

  5. Handler 消息传递机制

    1,Handler 的概念Handler 是用来干什么的?1)执行计划任务,可以在预定的时间执行某些任务,可以模拟定时器 2)线程间通信.在Android的应用启动时,会创建一个主线程,主线程会创建一 ...

  6. Kth Smallest Element in a BST

    Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. Not ...

  7. 学习C++.Primer.Plus 6 分支语句和逻辑操作符

    ||. &&操作符是一个顺序点 < 操作符从左向右结合 ; < age < )//17<age为true, = 1,肯定 < 27.所以为整个条件为tru ...

  8. 基于VirtualBox安装Ubuntu图文教程

    基于VirtualBox虚拟机安装Ubuntu图文教程 一. 下载安装VirtualBox 官网下载VirtualBox,目前版本:VirtualBox 5.1.8 for Windows hosts ...

  9. C/C++实践笔记_002编译和链接

    1.要卡死程序用异步,同步的话开一个就关一个值为非0死循环.预处理优先于编译,别称预编译main函数死循环2.程序总是从main函数开始执行的C语言本身不提供输入输出语句print等来自于stdio库 ...

  10. [BZOJ1264][AHOI2006]Match(DP+树状数组)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1264 分析: 考虑做一般的LCS的时候,更新结果的条件是a[i]==b[j]时候 于是 ...