1500: [NOI2005]维修数列

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 12544  Solved: 3970
[Submit][Status][Discuss]

Description

Input

输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

Output

对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

Sample Input

9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM

Sample Output

-1
10
1
10

HINT

Source

打掉大boss了,一边抄一边写。

因为插入的数总共为4000000个,所以我们可以暴力地每个点直接插入,插入时,我们把新插入的元素建成一棵小树,再挂到大树上。

删除一样,转到那个节点,然后删除,但是这里要一个个删除,因为内存要循环利用。直接暴力删除,把节点放进一个栈中,用的时候拿出来,因为一共只有4000000个元素,绝对不会超时。

修改是打一个懒标记,tag[x]=c,然后pushdown即可。

翻转同上。

求和也是利用标记,sum[x]=sum[child[x][0]]+sum[child[x][1]]+key[x]

最后一个我们需要维护三个值,x节点表示的区间,lm[x]表示从x节点的区间最左端开始,最大的和是多少,rm[x]则是右边,mx[x]则表示这个节点的最大和

mx[x]=max(mx[child[x][0]],mx[child[x][1]],max(rm[child[x][0]],0)+key[x]+max(0,lm[child[x][1]])) 自己拿手画一下,想一下即可。

注意:pushdown要更新自己的sum[x],key[x],然后也要把自己的儿子节点child[x][0],child[x][1]也更新掉,翻转也是,我不知道为什么,这里查了两个小时才发现。

makesame的初始值要设成-1001,因为更新的数在[-1000,1000]之间。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<stack>
  4. #include<vector>
  5. using namespace std;
  6. #define N 1000010
  7. #define inf -1101
  8. stack<int> s;
  9. int n,m,root,cnt;
  10. int size[N],child[N][],lm[N],rm[N],key[N],mx[N],sum[N];
  11. int tag1[N],tag2[N],fa[N],a[N];
  12. void update(int x)
  13. {
  14. size[x]=size[child[x][]]+size[child[x][]]+;
  15. sum[x]=sum[child[x][]]+sum[child[x][]]+key[x];
  16. mx[x]=max(max(mx[child[x][]],mx[child[x][]]),
  17. max(rm[child[x][]],)+key[x]+max(lm[child[x][]],));
  18. lm[x]=max(lm[child[x][]],sum[child[x][]]+key[x]+max(,lm[child[x][]]));
  19. rm[x]=max(rm[child[x][]],sum[child[x][]]+key[x]+max(,rm[child[x][]]));
  20. }
  21. void paint(int x)
  22. {
  23. tag2[x]^=;
  24. swap(child[x][],child[x][]);
  25. swap(lm[x],rm[x]);
  26. }
  27. void paint(int x,int c)
  28. {
  29. if(!x) return;
  30. tag1[x]=key[x]=c; sum[x]=size[x]*c;
  31. lm[x]=rm[x]=mx[x]=max(sum[x],key[x]);
  32. }
  33. void pushdown(int x)
  34. {
  35. if(tag1[x]!=inf)
  36. {
  37. paint(child[x][],tag1[x]);//更新儿子节点
  38. paint(child[x][],tag1[x]);//更新儿子节点
  39. tag1[x]=inf;
  40. }
  41. if(tag2[x])
  42. {
  43. tag2[x]^=;
  44. if(child[x][]) paint(child[x][]);//更新儿子节点
  45. if(child[x][]) paint(child[x][]);//更新儿子节点
  46. }
  47. }
  48. void zig(int x)
  49. {
  50. int y=fa[x];
  51. fa[x]=fa[y]; child[fa[x]][child[fa[x]][]==y]=x;
  52. child[y][]=child[x][];
  53. fa[child[x][]]=y;
  54. child[x][]=y; fa[y]=x;
  55. update(y); update(x);
  56. }
  57. void zag(int x)
  58. {
  59. int y=fa[x];
  60. fa[x]=fa[y]; child[fa[x]][child[fa[x]][]==y]=x;
  61. child[y][]=child[x][];
  62. fa[child[x][]]=y;
  63. child[x][]=y; fa[y]=x;
  64. update(y); update(x);
  65. }
  66. void splay(int x,int t)
  67. {
  68. while(fa[x]!=t)
  69. {
  70. pushdown(x);
  71. int y=fa[x],z=fa[y];
  72. if(z==t)
  73. {
  74. x==child[y][]?zig(x):zag(x); break;
  75. }
  76. x==child[y][]?zig(x):zag(x);
  77. x==child[z][]?zig(x):zag(x);
  78. }
  79. if(!t) root=x;
  80. update(root);
  81. }
  82. int find(int x,int rank)
  83. {
  84. pushdown(x);
  85. if(size[child[x][]]+==rank) return x;
  86. if(size[child[x][]]>=rank) return find(child[x][],rank);
  87. else return find(child[x][],rank-size[child[x][]]-);
  88. }
  89. int newnode()
  90. {
  91. int ret=;
  92. if(!s.empty())
  93. {
  94. ret=s.top();
  95. s.pop();
  96. } else ret=++cnt;
  97. return ret;
  98. }
  99. void build(int l,int r,int&x,int last)
  100. {
  101. int mid=(l+r)>>;
  102. x=newnode(); key[x]=a[mid]; fa[x]=last;
  103. if(l<=mid-) build(l,mid-,child[x][],x);
  104. if(mid+<=r) build(mid+,r,child[x][],x);
  105. update(x);
  106. }
  107. void insert(int l,int r)
  108. {
  109. int x=find(root,l),y=find(root,l+);//在l之后在l+1之前
  110. splay(x,); splay(y,root);
  111. for(int i=;i<=r-l+;i++) scanf("%d",&a[i]);
  112. build(,r-l+,child[child[root][]][],child[root][]);
  113. update(child[root][]); update(root);
  114. }
  115. void erase(int&x)
  116. {
  117. if(!x) return;
  118. s.push(x);
  119. fa[x]=; key[x]=size[x]=sum[x]=tag2[x]=;
  120. tag1[x]=inf;
  121. lm[x]=rm[x]=mx[x]=-(<<);
  122. erase(child[x][]);
  123. erase(child[x][]);
  124. x=;
  125. }
  126. void del(int l,int r)
  127. {
  128. int x=find(root,l-),y=find(root,r+);
  129. splay(x,); splay(y,root);
  130. erase(child[child[root][]][]);
  131. update(child[root][]); update(root);
  132. }
  133. void makesame(int l,int r,int c)
  134. {
  135. int x=find(root,l-),y=find(root,r+);
  136. splay(x,); splay(y,root);
  137. paint(child[child[root][]][],c);//更新儿子节点
  138. update(child[root][]); update(root);
  139. splay(child[child[root][]][],);
  140. }
  141. void reverse(int l,int r)
  142. {
  143. int x=find(root,l-),y=find(root,r+);
  144. splay(x,); splay(y,root);
  145. int b=child[child[root][]][];
  146. if(b) paint(b);//更新儿子节点
  147. splay(child[child[root][]][],);
  148. }
  149. void getsum(int l,int r)
  150. {
  151. int x=find(root,l-),y=find(root,r+);
  152. splay(x,); splay(y,root);
  153. printf("%d\n",sum[child[child[root][]][]]);
  154. }
  155. void maxsum()
  156. {
  157. printf("%d\n",mx[root]);
  158. }
  159. int main()
  160. {
  161. for(int i=;i<=N;i++) tag1[i]=inf;
  162. scanf("%d%d",&n,&m);
  163. for(int i=;i<=n+;i++)
  164. {
  165. scanf("%d",&a[i]);
  166. }
  167. mx[]=mx[n+]=lm[]=lm[n+]=rm[]=rm[n+]=mx[]=
  168. lm[]=rm[]=a[]=a[n+]=-(<<);
  169. int x; build(,n+,x,);
  170. root=;
  171. while(m--)
  172. {
  173. char s[]; int pos,tot,c; scanf("%s",s);
  174. if(s[]=='S')
  175. {
  176. scanf("%d%d",&pos,&tot);
  177. insert(pos+,pos+tot);
  178. }
  179. if(s[]=='L')
  180. {
  181. scanf("%d%d",&pos,&tot);
  182. del(pos+,pos+tot);
  183. }
  184. if(s[]=='K')
  185. {
  186. scanf("%d%d%d",&pos,&tot,&c);
  187. if(tot>) makesame(pos+,pos+tot,c);
  188. }
  189. if(s[]=='V')
  190. {
  191. scanf("%d%d",&pos,&tot);
  192. reverse(pos+,pos+tot);
  193. }
  194. if(s[]=='T')
  195. {
  196. scanf("%d%d",&pos,&tot);
  197. getsum(pos+,pos+tot);
  198. }
  199. if(s[]=='X')
  200. {
  201. maxsum();
  202. }
  203. }
  204. return ;
  205. }

bzoj1500的更多相关文章

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

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

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

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

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

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

  4. 【BZOJ1500】[NOI2005]维修数列 Splay

    [BZOJ1500][NOI2005]维修数列 Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行 ...

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

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

  6. 【BZOJ1500】维修数列(splay)

    题意: 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述中的 ...

  7. [bzoj1500][NOI2005]维修数列_非旋转Treap

    维修数列 bzoj-1500 NOI-2005 题目大意:给定n个数,m个操作,支持:在指定位置插入一段数:删除一个数:区间修改:区间翻转.查询:区间和:全局最大子序列. 注释:$1\le n_{ma ...

  8. BZOJ1500[NOI2005]维修数列

    Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一 ...

  9. BZOJ1500: [NOI2005]维修数列[splay ***]

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

随机推荐

  1. JavaWeb_day05cookie_session_HttpSession

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! 两个会话的技术cookie session 会话概念 ...

  2. Servlet3.0的注解

    1.@WebListener注解 表示的就是我们之前的在xml中配置的 <listener> <listener-class>ListenerClass</listene ...

  3. java多线程实现方式

    一.什么是线程? 线程:程序中一个单一的顺序控制流程.进程内一个相对独立的.可调度的执行单元,是系统独立调度和分派CPU的基本单位. 多线程:单个程序中同时运行多个线程完成不同的工作,称为多线程. 特 ...

  4. 关于Linux下转换oracle字符集

    前阵子给以同事导oracle数据库,但是发现导入后数据都是乱码,下面是自己解决这个问题的一些小整理. 比如: #su oralce $export ORACLE_SID=orcl $export OR ...

  5. Inter1-关于i++和++i

    Q:关于i++和++i计算以下公式的结果 ```public static void main(String[] args) { int i = 1; System.out.println(" ...

  6. java类与实例

    最近在看设计模式,感觉自己对java的三大特性的理解不够清晰,搞不清楚抽象类.接口.泛型的用处和优缺点.设计模式学了一半,想着还是停下来脑补一下java的基础,就从java对象开始吧. 一.java对 ...

  7. 2016年6月份那些最实用的 jQuery 插件专辑

    jQuery 是一个快速.流行的 JavaScript 库,jQuery 用于文档处理.事件处理.动画和 Ajax 交互非常简单,学习曲线也很平坦.2016年6月的 jQuery 插件专辑里,我们选择 ...

  8. low security dvwa--SQL Injection(Blind)

    1.输入单引号,结果如下: 2.输入永真式 ' and 1=1; -- 结果如下: 多次测试,如果输入的条件为假,就会返回1中的结果,为真则返回2中的结果,由此说明这属于SQL盲注. 3.猜解用户名长 ...

  9. DX12龙书第6章习题

    1. { { , DXGI_FORMAT_R32G32B32_FLOAT, , , D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, }, { , DXGI_FO ...

  10. JS 与OC 交互篇

    完美记录交互 CSDN博客: (OC调用JS) http://blog.csdn.net/lwjok2007/article/details/47058101 (JS调用OC) http://blog ...