首页 > 代码库 > SPOJ 4487 Splay 基本操作

SPOJ 4487 Splay 基本操作

插入操作,删除操作和置换操作都是单点的,所以不需要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));
    }

<style type="text/css">.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; } </style>

这个题目的代码

   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:  }
<style type="text/css">.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; } </style>