http://www.lydsy.com/JudgeOnline/problem.php?id=1500

模板不打熟你确定考场上调试得出来?

首先有非常多的坑点。。。我遇到的第一个就是,如何pushup。。。。。。。。。。。。sad。。

写了一大串。。。可是感觉。。。写不下去了。。。看别人怎么写吧。。。

orz

首先这个节点代表的这个区间我们维护mxl和mxr表示整个区间从左向右和从右向左能得到的最大序列和。。

然后我无脑不思考没有用好我们的定义,写了一大串的转移。。。

其实就是几个字。。

  1. void pushup() {
  2. s=1+ch[0]->s+ch[1]->s;
  3. sum=ch[0]->sum+ch[1]->sum+w;
  4. int l=max(0, ch[1]->mxl), r=max(0, ch[0]->mxr); //这里一定要注意
  5. mxl=max(ch[0]->mxl, ch[0]->sum+w+l); //不单独考虑ch[0]->sum的原因是我们假设了ch[0]->mxl是最优了
  6. mxr=max(ch[1]->mxr, ch[1]->sum+w+r);
  7. mx=max(l+w+r, max(ch[0]->mx, ch[1]->mx));
  8. }

555

然后有很多坑点我在注释里写。首先我的区间翻转那里我老是写错,我的getrange(l, r)是将区间l~r旋转到keytree那里,所以root是l-1,root->ch[1]是r+1,然后如果是要在某个点后边插入是getrange(pos+1, pos),一定要注意!

然后是pushdown的坑点,原来一直是写先tag后操作,现在变成了先操作后tag的形式,这点很重要!!!因为我们维护的size是整棵树的,当只有旋转到keytree下时,size不会统计到边界端点,所以整棵子树的size都是正确的!所以必须要在旋转回去前维护好所有的信息,而不是先打tag!一定要注意!!!之前一直调试不出来就是因为一直在考虑边界点怎么怎么影响。。。。。。然后各种搞不出来。。于是就这么简单的解决了orz

然后有一个地方我忘记了,,,就是每一个从树中获取信息的并向子树走的一定要pushdown!!我被select那里没有pushdown坑了好久

然后注意每一次更新子树后要pushup或者splay!!!一定要注意!!

还有询问前一定要将区间翻转后在区间进行查询!!!!一定要注意!!!

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cmath>
  4. #include <string>
  5. #include <iostream>
  6. #include <algorithm>
  7. #include <queue>
  8. #include <set>
  9. #include <map>
  10. using namespace std;
  11. typedef long long ll;
  12. #define rep(i, n) for(int i=0; i<(n); ++i)
  13. #define for1(i,a,n) for(int i=(a);i<=(n);++i)
  14. #define for2(i,a,n) for(int i=(a);i<(n);++i)
  15. #define for3(i,a,n) for(int i=(a);i>=(n);--i)
  16. #define for4(i,a,n) for(int i=(a);i>(n);--i)
  17. #define CC(i,a) memset(i,a,sizeof(i))
  18. #define read(a) a=getint()
  19. #define print(a) printf("%d", a)
  20. #define dbg(x) cout << (#x) << " = " << (x) << endl
  21. #define error(x) (!(x)?puts("error"):0)
  22. inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
  23.  
  24. const int oo=~0u>>2;
  25. int n, m;
  26. struct node *null;
  27. struct node {
  28. node *ch[2], *fa;
  29. bool rev, tag;
  30. int sum, s, mx, mxl, mxr, w;
  31. void pushup() {
  32. s=1+ch[0]->s+ch[1]->s;
  33. sum=ch[0]->sum+ch[1]->sum+w;
  34. int l=max(0, ch[1]->mxl), r=max(0, ch[0]->mxr);
  35. mxl=max(ch[0]->mxl, ch[0]->sum+w+l);
  36. mxr=max(ch[1]->mxr, ch[1]->sum+w+r);
  37. mx=max(l+w+r, max(ch[0]->mx, ch[1]->mx));
  38. }
  39. void upd(const int &k) {
  40. if(this==null) return;
  41. w=k;
  42. sum=s*k;
  43. mx=mxl=mxr=max(k, k*s);
  44. tag=true;
  45. }
  46. void upd2() {
  47. if(this==null) return;
  48. rev=!rev;
  49. swap(ch[0], ch[1]);
  50. swap(mxl, mxr);
  51. }
  52. void pushdown() {
  53. if(rev) {
  54. rev=false;
  55. ch[0]->upd2();
  56. ch[1]->upd2();
  57. }
  58. if(tag) {
  59. tag=false;
  60. ch[0]->upd(w);
  61. ch[1]->upd(w);
  62. }
  63. }
  64. bool d() { return fa->ch[1]==this; }
  65. void setc(node *c, bool d) { ch[d]=c; c->fa=this; }
  66. void init(const int &k) { sum=mx=mxl=mxr=w=k; }
  67. void set(int c=0) { ch[0]=ch[1]=fa=null; rev=tag=false; sum=w=mx=mxl=mxr=c; s=1; }
  68. }*root, *s[1000005];
  69. void rot(node *x) {
  70. node *fa=x->fa;
  71. fa->pushdown(); x->pushdown(); bool d=x->d();
  72. fa->fa->setc(x, fa->d());
  73. fa->setc(x->ch[!d], d);
  74. x->setc(fa, !d);
  75. fa->pushup();
  76. if(fa==root) root=x;
  77. }
  78. void splay(node *x, node *fa=null) {
  79. x->pushdown();
  80. while(x->fa!=fa)
  81. if(x->fa->fa==fa) rot(x);
  82. else x->d()==x->fa->d()?(rot(x->fa), rot(x)):(rot(x), rot(x));
  83. x->pushup();
  84. }
  85. node *sel(node *x, const int &k) {
  86. x->pushdown();
  87. int s=x->ch[0]->s;
  88. if(s==k) return x;
  89. if(k>s) return sel(x->ch[1], k-s-1); return sel(x->ch[0], k);
  90. }
  91. node *getrange(const int &l, const int &r) {
  92. splay(sel(root, l-1));
  93. splay(sel(root, r+1), root);
  94. return root->ch[1];
  95. }
  96. int top;
  97. node *newnode(int c=0) {
  98. node *ret;
  99. if(top) ret=s[top--];
  100. else ret=new node;
  101. ret->set(c);
  102. return ret;
  103. }
  104. void build(node *&x, const int &l, const int &r) {
  105. if(l>r) return;
  106. x=newnode();
  107. if(l==r) { x->init(getint()); return; }
  108. int m=(l+r)>>1;
  109. build(x->ch[0], l, m-1);
  110. x->init(getint());
  111. build(x->ch[1], m+1, r);
  112. if(l<=m-1) x->ch[0]->fa=x;
  113. if(m+1<=r) x->ch[1]->fa=x;
  114. x->pushup();
  115. }
  116. void insert() {
  117. int pos=getint(), tot=getint();
  118. node *x;
  119. build(x, 1, tot);
  120. node *fa=getrange(pos+1, pos); //注意getrange的地方
  121. fa->setc(x, 0);
  122. root->ch[1]->pushup();
  123. root->pushup();
  124. }
  125. void cln(node *x) {
  126. if(x==null) return;
  127. cln(x->ch[0]);
  128. cln(x->ch[1]);
  129. s[++top]=x;
  130. }
  131. void dele() {
  132. int l=getint(), r=l+getint()-1;
  133. node *fa=getrange(l, r);
  134. cln(fa->ch[0]);
  135. fa->ch[0]=null;
  136. root->ch[1]->pushup();
  137. root->pushup();
  138. }
  139. void ask1() {
  140. int l=getint(), r=l+getint()-1;
  141. node *x=getrange(l, r)->ch[0];
  142. printf("%d\n", x->sum);
  143. }
  144. void ask2() {
  145. node *x=getrange(1, root->s-2)->ch[0];
  146. printf("%d\n", x->mx);
  147. }
  148. void fix1() {
  149. int l=getint(), r=l+getint()-1, c=getint();
  150. node *x=getrange(l, r)->ch[0];
  151. x->upd(c);
  152. root->ch[1]->pushup();
  153. root->pushup();
  154. }
  155. void fix2() {
  156. int l=getint(), r=l+getint()-1;
  157. node *x=getrange(l, r)->ch[0];
  158. x->upd2();
  159. root->ch[1]->pushup();
  160. root->pushup();
  161. }
  162. void init() {
  163. null=newnode(-oo);
  164. null->ch[0]=null->ch[1]=null->fa=null; null->s=null->sum=null->w=0;
  165. root=newnode();
  166. node *c=newnode();
  167. root->setc(c, 1);
  168.  
  169. node *t;
  170. build(t, 1, n);
  171. root->ch[1]->setc(t, 0);
  172. root->ch[1]->pushup();
  173. root->pushup();
  174. }
  175. int main() {
  176. read(n); read(m);
  177. init();
  178. char s[15];
  179. for1(i, 1, m) {
  180. scanf("%s", s+1);
  181. char ch=s[3];
  182. if(ch=='S') insert(); //INSERT
  183. else if(ch=='L') dele(); //DELETE
  184. else if(ch=='T') ask1(); //GET-SUM
  185. else if(ch=='X') ask2(); //MAX-SUM
  186. else if(ch=='K') fix1(); //MAKE-SAME
  187. else if(ch=='V') fix2(); //REVERSE
  188. //P(root, 1);
  189. }
  190. return 0;
  191. }

  


Description

Input

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

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

【BZOJ】1500: [NOI2005]维修数列(splay+变态题)的更多相关文章

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

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

  2. BZOJ 1500: [NOI2005]维修数列 (splay tree)

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

  3. bzoj1500: [NOI2005]维修数列 (Splay+变态题)

    Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 11353  Solved: 3553 [Submit][Status][Discuss] Descrip ...

  4. [BZOJ 1500] [NOI2005] 维修数列

    题目链接:BZOJ - 1500 题目分析 我要先说一下,这道题我写了一晚上,然后Debug了一整个白天..........再一次被自己的蒟蒻程度震惊= = 这道题是传说中的Splay维护数列的Bos ...

  5. BZOJ 1500 [NOI2005]维修数列 FHQ Treap

    终于A了这题...这题还是很好...但是我太菜...重构了三遍qwq FHQ Treap大法好!qwq...~~ Ins:直接拿输入造一棵树,把原来的树split成[1,pos],[pos+1,n], ...

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

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

  7. 【BZOJ】1500: [NOI2005]维修数列

    [算法]splay [题解]数据结构 感谢Occult的模板>_<:HYSBZ 1500 维修数列 #include<cstdio> #include<cctype> ...

  8. BZOJ1500 [NOI2005]维修数列(Splay tree)

    [Submit][Status][Discuss] Description 请写一个程序,要求维护一个数列,支持以下 6 种操作: 请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格 Inp ...

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

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

随机推荐

  1. JavaScript数组方法说明

    JavaScript的数组方法有: http://www.w3school.com.cn/jsref/jsref_obj_array.asp 其中:concat.join和slice方法都不会修改原数 ...

  2. 解决Android 5.1系统以上通知状态栏小图标仅仅显示白色问题

    看上图,想必大家都有遇到过吧.近期俺也遇到了,找到了解决方法,如今分享下也做个记录哈. 问题发生的规则是Android5.1或者以上的手机系统使用了非常多的颜色的通知图标,就会出现,怎么解决呢,非常e ...

  3. 具有SSM框架的CRUD与多条件查询

    概述 居于ssm版本的crud跟多添加查询, 并带分页的demo 详细 代码下载:http://www.demodashi.com/demo/13653.html 一.功能展示 部门CRUD: 员工C ...

  4. android多线程进度条

    多线程实现更新android进度条. 实例教程,详细信息我已经注释   android多线程进度条   01package com.shougao.hello; 02 03import android ...

  5. 摘:LIB和DLL的区别与在VC中的使用

    共有两种库:一种是LIB包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供,称为动态链接库dynamic link library.一种是LIB包含函数 ...

  6. android何如获取SIM卡提供国家代码(ISO)

    TelephonyManager telManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE); telMana ...

  7. 基于Bootstrap的Asp.net Mvc 分页的实现(转)

    最近写了一个mvc 的 分页,样式是基于 bootstrap 的 ,提供查询条件,不过可以自己写样式根据个人的喜好,以此分享一下.首先新建一个Mvc 项目,既然是分页就需要一些数据,我这 边是模拟了一 ...

  8. Android自己定义截屏功能,相似QQ截屏

    由于公司业务需求 须要对一个屏幕进行截屏.但自带的截屏功能是远远不够项目的功能需求 ,我们是做一个画板软件 .须要的像QQ那样截屏之后 ,能够看到我们自己定义的工具.有画笔,button等等 .and ...

  9. python 中写hive 脚本

    1.直接执行.sql脚本 import numpy as np import pandas as pd import lightgbm as lgb from pandas import DataFr ...

  10. B/S打印解决方案参考

    使用Lodop 插件,该插件占用8000端口,未使用过,仅知依赖浏览器打印 http://blog.csdn.net/harderxin/article/details/17262945 强大的web ...