【题目链接】

点击打开链接

【算法】

本题所运用的也是Splay的区间操作,但是实现较为困难

INSERT操作

            将pos splay至根节点,pos+1 splay至根节点的右节点,然后对根节点的右节点的左节点建树即可

DELETE操作

            将l-1 splay至根节点, r+1 splay至根节点的右节点,直接“砍断”根节点的右节点的左节点

MAKE_SAME操作

            将l-1 splay至根节点,r+1 splay至根节点的右节点,给根节点的右节点的左节点打上标记

REVERSE操作

            将l-1 splay至根节点,r+1 splay至根节点的右节点,给根节点的右节点的左节点打上标记

GET_SUM操作

            将l-1 splay至根节点,r+1 splay至根节点的右节点,直接输出根节点的右节点的左节点的sum

MAX_SUM操作

            此操作的实现类似于树形DP :

我们不妨给每个节点增加三个域

lmax :从这个节点所代表的区间的左端点开始向右延伸的最大和

rmax :从这个节点所代表的区间的右端点开始像左延伸的最大和

max : 该节点所代表区间的最大连续子段和

那么,lmax该如何取值?

令根节点为root,根节点的左儿子为lc,根节点的右儿子为rc

            我们可以分情况讨论 :

lmax[root]不包括root,lmax[root] = lmax[lc]

            lmax[root]包括root,那么 : 若不向右继续延伸,则lmax[root] = tot[lc] + val[root],若向右延伸,

lmax[root] = tot[lc] + val[root] + lmax[rc]

            我们只要在这三者中取最大值就可以了

rmax同理

那么,max又该如何取值呢?

我们还是分情况讨论 :

令根节点为root,根节点的左儿子为rc,根节点的右儿子为rc

max[root]不包括root,max[root] = max{max[lc],max[rc]}

            max[root]包括root,那么 : 若不向右也不向左延伸,则max[root] = val[root],若向左延伸,

max[root] = val[root] + rmax[lc]

            若向右延伸,则 :

max[root] = val[root] + lmax[rc]

            若两边同时延伸,则 :

max[root] = val[root] + rmax[rc] + lmax[lc]

            只需在这五者中取最大值即可

关于内存池 :

            由于本题数据量较大,我们要进行内存回收,内存回收方法如下 :

我们建立一个内存池,开始时将所有可用空间都放入内存池,插入一个节点时,我们从内存池弹出一个节点,

分配给这个节点,删除时,我们将要删除的节点放回内存池,如果是删除一棵子树,则将整棵子树放回内存池

这个内存池可以用栈,队列,链表等许多数据结构来维护,笔者选用的是栈,由于维护方法比较简单,笔者不再赘述

【代码】

本题的细节很多,写代码时一定要严谨!

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define MAXN 20000
  4. #define MAXX 500000
  5. const int INF = 2e9;
  6.  
  7. int i,N,M,tot,pos,val;
  8. int a[MAXX+];
  9. char opt[];
  10. stack<int> stk;
  11.  
  12. template <typename T> inline void read(T &x) {
  13. int f = ; x = ;
  14. char c = getchar();
  15. for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; }
  16. for (; isdigit(c); c = getchar()) x = x * + c - '';
  17. x *= f;
  18. }
  19.  
  20. template <typename T> inline void write(T x) {
  21. if (x < ) { putchar('-'); x = -x; }
  22. if (x > ) write(x/);
  23. putchar(x%+'');
  24. }
  25.  
  26. template <typename T> inline void writeln(T x) {
  27. write(x);
  28. puts("");
  29. }
  30.  
  31. struct Splay {
  32. int root;
  33. struct Node {
  34. int fa,son[],size,lmax,rmax,tot,
  35. Max,val,lazy;
  36. bool rev;
  37. } Tree[MAXX+];
  38. inline bool get(int x) {
  39. return Tree[Tree[x].fa].son[] == x;
  40. }
  41. inline void build(int index,int l,int r) {
  42. int id,mid;
  43. mid = (l + r) >> ;
  44. Tree[index].lazy = INF;
  45. Tree[index].rev = ;
  46. Tree[index].val = a[mid];
  47. if (l == r) {
  48. Tree[index].size = ;
  49. Tree[index].lmax = Tree[index].rmax = Tree[index].Max = Tree[index].tot = a[mid];
  50. return;
  51. }
  52. if (l < mid) {
  53. id = stk.top();
  54. stk.pop();
  55. Tree[index].son[] = id;
  56. Tree[id].fa = index;
  57. build(id,l,mid-);
  58. }
  59. if (mid < r) {
  60. id = stk.top();
  61. stk.pop();
  62. Tree[index].son[] = id;
  63. Tree[id].fa = index;
  64. build(id,mid+,r);
  65. }
  66. update(index);
  67. }
  68. inline void update(int index) {
  69. if (!index) return;
  70. Tree[index].tot = Tree[Tree[index].son[]].tot + Tree[Tree[index].son[]].tot + Tree[index].val;
  71. Tree[index].size = Tree[Tree[index].son[]].size + Tree[Tree[index].son[]].size + ;
  72. Tree[index].lmax = max(Tree[Tree[index].son[]].lmax,Tree[Tree[index].son[]].tot+max(Tree[Tree[index].son[]].lmax,)+Tree[index].val);
  73. Tree[index].rmax = max(Tree[Tree[index].son[]].rmax,Tree[Tree[index].son[]].tot+max(Tree[Tree[index].son[]].rmax,)+Tree[index].val);
  74. Tree[index].Max = max(Tree[Tree[index].son[]].Max,max(Tree[Tree[index].son[]].Max,Tree[index].val+max(Tree[Tree[index].son[]].rmax,)+max(Tree[Tree[index].son[]].lmax,)));
  75. }
  76. inline void pushdown(int index) {
  77. int tmp;
  78. if (Tree[index].lazy != INF) {
  79. tmp = Tree[index].lazy;
  80. Tree[index].lazy = INF;
  81. if (Tree[index].son[]) Tree[Tree[index].son[]].tot = Tree[Tree[index].son[]].size * tmp;
  82. if (Tree[index].son[]) Tree[Tree[index].son[]].tot = Tree[Tree[index].son[]].size * tmp;
  83. if (Tree[index].son[]) Tree[Tree[index].son[]].val = tmp;
  84. if (Tree[index].son[]) Tree[Tree[index].son[]].val = tmp;
  85. if (Tree[index].son[]) Tree[Tree[index].son[]].lmax = Tree[Tree[index].son[]].rmax = Tree[Tree[index].son[]].Max = max(tmp,Tree[Tree[index].son[]].size*tmp);
  86. if (Tree[index].son[]) Tree[Tree[index].son[]].lmax = Tree[Tree[index].son[]].rmax = Tree[Tree[index].son[]].Max = max(tmp,Tree[Tree[index].son[]].size*tmp);
  87. if (Tree[index].son[]) Tree[Tree[index].son[]].lazy = tmp;
  88. if (Tree[index].son[]) Tree[Tree[index].son[]].lazy = tmp;
  89. }
  90. if (Tree[index].rev) {
  91. swap(Tree[index].son[],Tree[index].son[]);
  92. swap(Tree[Tree[index].son[]].lmax,Tree[Tree[index].son[]].rmax);
  93. swap(Tree[Tree[index].son[]].lmax,Tree[Tree[index].son[]].rmax);
  94. Tree[Tree[index].son[]].rev ^= ;
  95. Tree[Tree[index].son[]].rev ^= ;
  96. Tree[index].rev = ;
  97. }
  98. }
  99. inline int query_pos(int x) {
  100. int index = root;
  101. while (true) {
  102. pushdown(index);
  103. if (x > Tree[Tree[index].son[]].size) {
  104. x -= Tree[Tree[index].son[]].size;
  105. if (x == ) return index;
  106. --x;
  107. index = Tree[index].son[];
  108. } else index = Tree[index].son[];
  109. }
  110. }
  111. inline void clear(int index) {
  112. Tree[Tree[index].fa].son[get(index)] = ;
  113. Tree[index].fa = ;
  114. stk.push(index);
  115. if (Tree[index].son[]) clear(Tree[index].son[]);
  116. if (Tree[index].son[]) clear(Tree[index].son[]);
  117. }
  118. inline void Insert(int index) {
  119. int id;
  120. int x = query_pos(index),
  121. y = query_pos(index+);
  122. splay(x,); splay(y,root);
  123. id = stk.top();
  124. stk.pop();
  125. build(id,,tot);
  126. Tree[Tree[root].son[]].son[] = id;
  127. Tree[id].fa = Tree[root].son[];
  128. update(Tree[root].son[]);
  129. update(root);
  130. }
  131. inline void rotate(int x) {
  132. int f = Tree[x].fa,g = Tree[f].fa,
  133. tmpx = get(x),tmpf = get(f);
  134. pushdown(f); pushdown(x);
  135. if (!f) return;
  136. Tree[f].son[tmpx] = Tree[x].son[tmpx^];
  137. if (Tree[x].son[tmpx^]) Tree[Tree[x].son[tmpx^]].fa = f;
  138. Tree[x].son[tmpx^] = f;
  139. Tree[f].fa = x;
  140. Tree[x].fa = g;
  141. if (g) Tree[g].son[tmpf] = x;
  142. update(f);
  143. update(x);
  144. }
  145. inline void splay(int x,int pos) {
  146. int f;
  147. for (f = Tree[x].fa; (f = Tree[x].fa) != pos; rotate(x)) {
  148. if (Tree[f].fa != pos)
  149. rotate(get(f) == get(x) ? (f) : (x));
  150. }
  151. if (!pos) root = x;
  152. }
  153. inline void modify(int l,int r,int v) {
  154. int x = query_pos(l-),
  155. y = query_pos(r+);
  156. splay(x,); splay(y,root);
  157. int tmp = Tree[Tree[root].son[]].son[];
  158. Tree[tmp].val = Tree[tmp].lazy = v;
  159. Tree[tmp].tot = v * Tree[tmp].size;
  160. Tree[tmp].lmax = Tree[tmp].rmax = Tree[tmp].Max = max(Tree[tmp].size*v,v);
  161. update(Tree[root].son[]);
  162. update(root);
  163. }
  164. inline void reverse(int l,int r) {
  165. int x = query_pos(l-),
  166. y = query_pos(r+);
  167. splay(x,); splay(y,root);
  168. Tree[Tree[Tree[root].son[]].son[]].rev ^= ;
  169. swap(Tree[Tree[Tree[root].son[]].son[]].lmax,Tree[Tree[Tree[root].son[]].son[]].rmax);
  170. }
  171. inline void erase(int l,int r) {
  172. int x = query_pos(l-),
  173. y = query_pos(r+);
  174. splay(x,); splay(y,root);
  175. clear(Tree[Tree[root].son[]].son[]);
  176. Tree[Tree[root].son[]].son[] = ;
  177. update(Tree[root].son[]);
  178. update(root);
  179. }
  180. int get_sum(int l,int r) {
  181. int x = query_pos(l-),
  182. y = query_pos(r+);
  183. splay(x,); splay(y,root);
  184. return Tree[Tree[Tree[root].son[]].son[]].tot;
  185. }
  186. int max_sum(int l,int r) {
  187. int x = query_pos(l-),
  188. y = query_pos(r+);
  189. splay(x,); splay(y,root);
  190. return Tree[Tree[Tree[root].son[]].son[]].Max;
  191. }
  192. } T;
  193.  
  194. int main() {
  195.  
  196. read(N); read(M);
  197.  
  198. for (i = ; i <= MAXX; i++) stk.push(i);
  199.  
  200. a[] = a[N+] = -INF;
  201. for (i = ; i <= N + ; i++) read(a[i]);
  202.  
  203. T.Tree[].lmax = T.Tree[].rmax = T.Tree[].Max = -INF;
  204. T.root = ;
  205. T.build(,,N+);
  206.  
  207. while (M--) {
  208. scanf("%s",&opt);
  209. if (opt[] == 'I') {
  210. read(pos); read(tot);
  211. for (i = ; i <= tot; i++) read(a[i]);
  212. T.Insert(pos+);
  213. N += tot;
  214. } else if (opt[] == 'D') {
  215. read(pos); read(tot);
  216. T.erase(pos+,pos+tot);
  217. N -= tot;
  218. } else if (opt[] == 'M' && opt[] == 'K') {
  219. read(pos); read(tot); read(val);
  220. T.modify(pos+,pos+tot,val);
  221. } else if (opt[] == 'R') {
  222. read(pos); read(tot);
  223. T.reverse(pos+,pos+tot);
  224. } else if (opt[] == 'G') {
  225. read(pos); read(tot);
  226. writeln(T.get_sum(pos+,pos+tot));
  227. } else if (opt[] == 'M' && opt[] == 'X') {
  228. writeln(T.max_sum(,N+));
  229. }
  230. }
  231.  
  232. return ;
  233.  
  234. }

【NOI 2005】 维修数列的更多相关文章

  1. NOI 2005 维修数列

    妈妈呀我终于过了!!!原来是数据坑我!!! 弃疗弃疗弃疗弃疗!!!!我调了一天呢....被GET_SUM 8 0打败了.... 啥也不说了....还是我太年轻.... 更新了一下常数,跑的还是可以的: ...

  2. bzoj 1500 [NOI 2005] 维修数列

    题目大意不多说了 貌似每个苦逼的acmer都要做一下这个splay树的模版题目吧 还是有很多操作的,估计够以后当模版了.... #include <cstdio> #include < ...

  3. NOI 2005维护数列

    题目描述 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 输入输出格式 输入格式: 输入文件的第 1 行包含两个数 N 和 M, ...

  4. 洛谷 2042 BZOJ 1500 NOI 2005 维护数列

    [题意概述] 维护一个数列,要求支持以下6种操作: [题解] 大Boss...可以用Treap解决 需要用到垃圾回收.线性建树. #include<cstdio> #include< ...

  5. 【BZOJ-1500】维修数列 Splay

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 11047  Solved: 3460[Submit][Statu ...

  6. [NOI2005] 维修数列

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 8397  Solved: 2530 Description In ...

  7. bzoj 1500: [NOI2005]维修数列 splay

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 6556  Solved: 1963[Submit][Status ...

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

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

  9. [BZOJ 1500]维修数列 [Splay Tree从进阶到住院]

    历尽艰辛终于A掉了这题QwQ 贴COGS评论区几句话=.= 策爷:"splay/块状链表的自虐题.".深刻理解到如果没有M倾向就不要去写这题了.. -Chenyao2333 记得b ...

  10. 【BZOJ1500】【NOI2005】维修数列(Splay)

    [BZOJ1500][NOI2005]维修数列(Splay) 题面 不想再看见这种毒瘤题,自己去BZOJ看 题解 Splay良心模板题 真的很简单 我一言不发 #include<iostream ...

随机推荐

  1. [bzoj1187][HNOI2007]神奇游乐园_插头dp

    bzoj-1187 HNOI-2007 神奇游乐园 题目大意:经历了一段艰辛的旅程后,主人公小P乘坐飞艇返回.在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细一看,才发现这 ...

  2. eclipse软件安装及python工程建立

    原文地址:http://www.cnblogs.com/halfacre/archive/2012/07/22/2603848.html 安装python解释器 安装PyDev: 首先需要去Eclip ...

  3. ELK之Kibana部署、收集系统日志、一个文件收集多个日志

    1.安装及配置Kibana cd /usr/local/src yum -y install kibana-5.4.0-x86_64.rpm grep "^[a-Z]" /etc/ ...

  4. UVA11825 Hackers' Crackdown

    题目描述 PDF 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例#1: 3 2 1 2 2 0 2 2 0 1 4 1 1 1 0 1 3 1 2 0 输出样例#1: Case 1: 3 ...

  5. Free web scraping | Data extraction | Web Crawler | Octoparse, Free web scraping

    Free web scraping | Data extraction | Web Crawler | Octoparse, Free web scraping 人才知了

  6. SystemTap 静态探针安装包

     yum install systemtap-sdt-devel 

  7. 大众车机天宝187A Hack笔记

    0×00前言 自从去年买了车,对汽车电子系统的兴趣就上来了.这不,前一阵子逛汽车论坛,发现了有网友将老版本的天宝车机被刷上了2017新帕萨特车机的系统,支持超级蓝牙和苹果CarPlay,百度CarLi ...

  8. Android4.4 Telephony流程分析——彩信(MMS)发送过程

    本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉. 彩信收发依靠WAP网络,在Android4.4中的实现基于Http协议的应用.下图为几个彩信传 ...

  9. push代码到github时,每次都要输入用户名和密码的问题

    问题原由 我在Github上 建立了一个小项目TauStreamingServer,可是在每次push代码 的时候,都要求输入用户名和密码,很是麻烦. 如何才能避免每次都输入用户名和密码呢? 解决办法 ...

  10. NSArray中存的是实体时的排序

    NSArray中存储的是实体时的排序 by 伍雪颖 NSSortDescriptor *sortDescriptor1 = [NSSortDescriptor sortDescriptorWithKe ...