插入操作,删除操作和置换操作都是单点的,所以不需要lazy标记。这个很简单,都是两次RotateTo,一次Splay操作就搞定。

求最大连续字段和的操作和线段树的题目类似,只需要保存最左边的连续最大字段和,最右边的连续最大字段和,整个子树的连续最大字段和就OK,整个子树的和就OK。

注意PushUp函数的写法就OK

//Problem Specific Function
void PushUp(int x )
{
int ll = sp[x].child[0], rr = sp[x].child[1];
// sz, lsum , rsum , msum, sum
sp[x].sz = 1 + sp[sp[x].child[0]].sz + sp[sp[x].child[1]].sz;
sp[x].sum = sp[x].val + sp[sp[x].child[0]].sum + sp[sp[x].child[1]].sum;
sp[x].lsum = max(sp[ll].lsum, sp[ll].sum + sp[x].val + max(sp[rr].lsum, 0));
sp[x].rsum = max(sp[rr].rsum, sp[rr].sum + sp[x].val + max(sp[ll].rsum , 0));
// 这里类似于线段树的
sp[x].msum = max(max(sp[ll].msum, sp[rr].msum), sp[x].val + max(sp[ll].rsum, 0) + max(sp[rr].lsum, 0));
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

这个题目的代码

   1:   
   2:  #include <cstdio>
   3:  #include <iostream>
   4:   
   5:  using namespace std;
   6:  #define INF 10009
   7:  #define MaxL 222222
   8:  #define keyTree   sp[sp[root].child[1]].child[0]
   9:   
  10:  struct SplayTreeNode
  11:  {
  12:      int parent, child[2];   // parent and child[0] left child[1] right
  13:      int sz, val;  // sz 表示当前节点为根的子树总节点个数.  val表示当前节点的键值。
  14:      int sum;    // 以x为根节点的子树的所有的和
  15:      int lsum;   // 以该点为根的子树的左子树最大的连续和 [left, x)
  16:      int rsum;   // 以该点为根的子树的右子树 最大的连续和 (x, right]
  17:      int msum;   // 以该点为根的子树中的连续最大字段和
  18:  };
  19:   
  20:  int num[MaxL];
  21:  struct SpalyTree
  22:  {
  23:      SplayTreeNode sp[MaxL];   // save space
  24:      int gc[MaxL];   // Garbage Collection idx
  25:      int root;  // root idx
  26:      int idx;   // Forward allocate tree
  27:      int idxrev; // garbage allocated nodes used for next allocation priority
  28:   
  29:      /*
  30:           A                        B
  31:         /   \    R(B,RR)->       /   \
  32:        B     C    <-R(A,LL)     D     A
  33:       / \                            /  \
  34:      D   E                          E    C
  35:      */
  36:      void Rotate(int x,int f)   // f ==0 l rot,1 r rot
  37:      {
  38:          int y = sp[x].parent;
  39:          //PushDown(y);
  40:          //PushDown(x);
  41:          sp[y].child[!f] = sp[x].child[f];
  42:          sp[sp[x].child[f]].parent = y;
  43:          sp[x].parent = sp[y].parent;
  44:          if(sp[x].parent)
  45:              sp[sp[y].parent].child[ sp[sp[y].parent].child[1] == y]= x;
  46:          sp[x].child[f] = y;
  47:          sp[y].parent = x;
  48:          PushUp(y);
  49:      }
  50:   
  51:      void Splay(int x, int goal)
  52:      {
  53:          //PushDown(x);
  54:          while(sp[x].parent != goal)
  55:          {
  56:              if(sp[sp[x].parent].parent == goal)
  57:                  Rotate(x, sp[sp[x].parent].child[0] == x);
  58:              else
  59:              {
  60:                  int y = sp[x].parent, z = sp[y].parent;
  61:                  int f = sp[z].child[0] == y;
  62:                  if(sp[y].child[f] == x)
  63:                      Rotate(x,!f), Rotate(x,f);
  64:                  else
  65:                      Rotate(y,f), Rotate(x,f);
  66:   
  67:              }
  68:          }
  69:          PushUp(x);
  70:          if(goal == 0) root = x;
  71:      }
  72:      //  把第k个的数转到goal下边,一般用来调整区间
  73:      int RotateTo(int k, int goal)
  74:      {
  75:          int x = root;
  76:          //PushDown(x);
  77:          while(sp[sp[x].child[0]].sz !=k)
  78:          {
  79:              if( k< sp [ sp[x].child[0] ].sz)
  80:                  x = sp[x].child[0];
  81:              else
  82:              {
  83:                  k -= sp[sp[x].child[0]].sz +1;
  84:                  x = sp[x].child[1];
  85:              }
  86:  //            PushDown(x);
  87:          }
  88:  //        cout<<"Rotate "<<x<<" goal "<<goal<<endl;
  89:          Splay(x, goal);
  90:          return x;
  91:      }
  92:   
  93:      void NewNode(int &x, int c)
  94:      {
  95:          if( idxrev) x = gc[--idxrev];
  96:          else  x = ++idx;
  97:          sp[x].child[1] = 0, sp[x].child[0] = 0, sp[x].parent = 0;
  98:          sp[x].sz = 1;
  99:          sp[x].val = sp[x].sum = sp[x].lsum = sp[x].rsum  = sp[x].msum = c;
 100:          //sp[x].lazy = 0;
 101:      }
 102:   
 103:      //把以x为祖先结点(x 也算)删掉放进内存池,回收内存
 104:      void eraseSubTree(int x)
 105:      {
 106:          int father = sp[x].parent;
 107:          int head = idxrev , tail = idxrev;
 108:          for (gc[tail++] = x ; head < tail ; head ++)
 109:          {
 110:              idxrev++;
 111:              if( sp[gc[head]].child[0]) gc[tail++] = sp[gc[head]].child[0];
 112:              if( sp[gc[head]].child[1]) gc[tail++] = sp[gc[head]].child[1];
 113:          }
 114:          sp[father].child[ sp[father].child[1] == x] = 0;
 115:          PushUp(father);
 116:      }
 117:   
 118:   
 119:      void makeTree(int &x, int l, int r, int parent)
 120:      {
 121:          if(l > r) return ;
 122:          int m = (l+r)>>1;
 123:          NewNode(x,num[m]);
 124:          makeTree(sp[x].child[0], l, m-1, x);
 125:          makeTree(sp[x].child[1], m+1, r, x);
 126:          sp[x].parent = parent;
 127:          PushUp(x);
 128:      }
 129:      void Init(int n)
 130:      {
 131:          idx = idxrev =  0;
 132:          root = 0;
 133:          sp[0].child[0] = sp[0].child[1] = sp[0].parent  = 0;
 134:          sp[0].sz = sp[0].sum = 0;
 135:          sp[0].val = sp[0].lsum = sp[0].rsum = sp[0].msum = -INF;
 136:          NewNode(root, -INF);
 137:          NewNode(sp[root].child[1], -INF);
 138:          sp[idx].parent = root;
 139:          sp[root].sz = 2;
 140:          makeTree( sp [sp[root].child[1] ].child[0] , 1, n, sp[root].child[1]);
 141:          PushUp(sp[root].child[1]);
 142:          PushUp(root);
 143:      }
 144:   
 145:      void Travel(int x)
 146:      {
 147:          if(x)
 148:          {
 149:              Travel( sp[x].child[0]);
 150:              printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d  sum = %2d\n",x, sp[x].child[0],sp[x].child[1],sp[x].parent,sp[x].sz,sp[x].val, sp[x].sum);
 151:              Travel( sp[x].child[1]);
 152:          }
 153:      }
 154:   
 155:      //Problem Specific Function
 156:      void PushUp(int x )
 157:      {
 158:          int ll = sp[x].child[0], rr = sp[x].child[1];
 159:          // sz, lsum , rsum , msum, sum
 160:          sp[x].sz = 1 + sp[sp[x].child[0]].sz + sp[sp[x].child[1]].sz;
 161:          sp[x].sum =  sp[x].val + sp[sp[x].child[0]].sum + sp[sp[x].child[1]].sum;
 162:          sp[x].lsum = max(sp[ll].lsum, sp[ll].sum + sp[x].val + max(sp[rr].lsum, 0));
 163:          sp[x].rsum = max(sp[rr].rsum, sp[rr].sum + sp[x].val + max(sp[ll].rsum , 0));
 164:          // 这里类似于线段树的
 165:          sp[x].msum = max(max(sp[ll].msum, sp[rr].msum), sp[x].val + max(sp[ll].rsum, 0) + max(sp[rr].lsum, 0));
 166:      }
 167:   
 168:      void Insert(int pos, int m)
 169:      {
 170:          RotateTo(pos - 1, 0);
 171:          RotateTo(pos, root);
 172:          int p = 0;
 173:          NewNode(p, m);
 174:          keyTree = p;
 175:          sp[p].parent = sp[root].child[1];
 176:          Splay(p,0);
 177:      }
 178:   
 179:      void Delete(int pos)
 180:      {
 181:          RotateTo(pos-1, 0);
 182:          RotateTo(pos+1, root);
 183:          eraseSubTree(keyTree);
 184:          Splay(sp[root].child[1], 0);
 185:      }
 186:   
 187:      void Replace(int pos, int m)
 188:      {
 189:          RotateTo(pos-1, 0);
 190:          RotateTo(pos+1, root);
 191:          int x = keyTree;
 192:          sp[x].val = sp[x].sum = sp[x].lsum = sp[x].rsum  = sp[x].msum = m;
 193:          Splay(keyTree,0);
 194:      }
 195:   
 196:      int Query(int l, int r)
 197:      {
 198:          RotateTo(l -1, 0);
 199:          RotateTo(r+1, root);
 200:   
 201:          int ret =  sp[keyTree].msum;
 202:          Splay(keyTree,0);
 203:          return ret;
 204:      }
 205:  } spt;
 206:   
 207:   
 208:  int main()
 209:  {
 210:  //    freopen("1.txt","r",stdin);
 211:      int n;
 212:      while(scanf("%d",&n)!=EOF)
 213:      {
 214:          for(int i=1; i<=n; i++)
 215:              scanf("%d",&num[i]);
 216:          spt.Init(n);
 217:          int q;
 218:          scanf("%d", &q);
 219:          while(q--)
 220:          {
 221:              char op[2];
 222:              scanf("%s",op);
 223:              int pos,m;
 224:              if(op[0]=='I')
 225:              {
 226:                  n++;
 227:                  scanf("%d%d",&pos, &m);
 228:                  spt.Insert(pos,m);
 229:              }
 230:              else if(op[0]=='D')
 231:              {
 232:                  n--;
 233:  //                scanf_(pos);
 234:                  scanf("%d", & pos);
 235:                  spt.Delete(pos);
 236:              }
 237:              else if(op[0]=='R')
 238:              {
 239:                  scanf("%d%d",&pos, &m);
 240:                  spt.Replace(pos,m);
 241:              }
 242:              else if(op[0]=='Q')
 243:              {
 244:                  scanf("%d%d", &pos, &m);
 245:                  printf("%d\n", spt.Query(pos,m));
 246:              }
 247:          }
 248:      }
 249:      return 0;
 250:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

SPOJ 4487 Splay 基本操作的更多相关文章

  1. spoj 4487. Can you answer these queries VI (gss6) splay 常数优化

    4487. Can you answer these queries VI Problem code: GSS6 Given a sequence A of N (N <= 100000) in ...

  2. SPOJ 4487. Can you answer these queries VI splay

    题目链接:点击打开链接 题意比較明显,不赘述. 删除时能够把i-1转到根,把i+1转到根下 则i点就在 根右子树 的左子树,且仅仅有i这一个 点 #include<stdio.h> #in ...

  3. Splay基本操作

    我们以一道题来引入吧! 传送门 题目说的很清楚,我们的数据结构要支持:插入x数,删除x数,查询数的排名和排名为x的数,求一个数前驱后继. 似乎用啥现有的数据结构都很难做到在O(nlogn)的复杂度中把 ...

  4. 【BZOJ-1552&3506】robotic sort&排序机械臂 Splay

    1552: [Cerc2007]robotic sort Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 806  Solved: 329[Submit][ ...

  5. splay详解(一)

    前言 Spaly是基于二叉查找树实现的, 什么是二叉查找树呢?就是一棵树呗:joy: ,但是这棵树满足性质—一个节点的左孩子一定比它小,右孩子一定比它大 比如说 这就是一棵最基本二叉查找树 对于每次插 ...

  6. splay:优雅的区间暴力!

    万年不更的blog主更新啦!主要是最近实在忙,好不容易才从划水做题的时间中抽出一段时间来写这篇blog 首先声明:这篇blog写的肯定会很基础...因为身为一个蒟蒻深知在茫茫大海中找到一个自己完全能够 ...

  7. POJ3468:A Simple Problem with Integers (线段树||树状数组||Splay解决基本问题的效率对比)

    You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of op ...

  8. Splay&LCT

    Splay && LCT \(\text{Splay}\) 基本操作 1.\(Zig \& Zag\) 其思想是维护中序遍历不变 实现中我们不真的用\(Zig\)或\(Zag\ ...

  9. 【学术篇】NOIP2017 d2t3 列队phalanx splay做法

    我可去他的吧.... ==============先胡扯些什么的分割线================== 一道NOIP题我调了一晚上...(其实是因为昨晚没有找到调试的好方法来的说...) 曾经我以 ...

随机推荐

  1. 转: Lua 语言 15 分钟快速入门

    看点: 1. 以很特殊的方式工,把Lua的语法全部输出一段,很容易让人记住..不错 转: http://blog.jobbole.com/70480/

  2. asp.net下的b/s架构

    最近一直在做asp.net下的b/s架构的程序.整理一下可以采用的架构. 简单三层架构 基于接口和工厂模式的三层 前台用jquery调用http请求(ashx),ashx再调用逻辑接口 虽然很早就知道 ...

  3. C# 实现远程控制软件的关键技术

    一.服务器端多线程Socket技术    用TcpListener进行侦听,接受客户端连接,有客户端连进来后开启处理线程处理数据,代码如下:    using System; using System ...

  4. Httpclient 和jsoup结和提取网页内容(某客学院视频链接)

    最近在极客学院获得体验会员3个月,然后就去上面看了看,感觉课程讲的还不错.整好最近学习Android,然后去上面找点视频看看.发现只有使用RMB买的会员才能在上面下载视频.抱着试一试的态度,去看他的网 ...

  5. hdoj1423 最长上升公共子序列

    hdoj1423 题目分析: 两个数组a[n1] , b[n2], 求最长上升公共子序列. 我们可用一维存储 f[i] 表示 b 数组以 j 结尾, 与 a[] 数组构成的最长公共上升子序列. 对数组 ...

  6. DOS批处理命令-SET命令

    SET是专门用来创建.设置.查看或删除环境变量. 总结了下,SET的使用语法一般有下面几种 1.SET 变量名=变量值 这边有一点要注意的,就是变量名和变量值中间的等号两端不需要也不能有空格 看看下面 ...

  7. html dom的加载

    操作HTML DOM文档的一个难题是,你的JavaScript代码可能在DOM完全载入之前运行,这会导致你的代码产生一些问题.页面加载时浏览器内部操作的顺序大致是这样的: 1. HTML被解析. 2. ...

  8. update更新多行数据(oracle)

    转自:http://blog.itpub.net/25322446/viewspace-767505 说明:笔记总结了在工作中遇到过的几种update方法和各种方法适用的范围. 1.单表更新方案:使用 ...

  9. javascript笔记——图片大小检测

    <html> <head> <script type="text/javascript"> var isIE = /msie/i.test(na ...

  10. 40个容易上瘾的HTML5网页游戏,总有一款适合你

    我记得姐姐家的孩子在刚刚才学会走路,说话还不能完整的时候就已经能自己用小手点出小游戏的网站来一个人自娱自乐.我一直在想这一代跟着计算机一起茁壮成长的孩子会不会也和美国那一代人一样,出现9岁的黑客和计算 ...