zoukankan      html  css  js  c++  java
  • 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));
        }

    这个题目的代码

       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
    ",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
    ", spt.Query(pos,m));
     246:              }
     247:          }
     248:      }
     249:      return 0;
     250:  }
  • 相关阅读:
    编译和安装在Windows上橡胶树 (Compiling and Installing Yate on Windows)
    Microsoft Sync Framework 2.1 可再发行程序包 Microsoft Sync Framework 1.0 SP1
    Kwickserver
    .net平台 基于 XMPP协议的即时消息服务端简单实现
    开源jabber(XMPP)架设内部即时通讯服务的解决方案
    www.mentalis.org/
    VM虚拟机ping不通局域网其他主机的解决办法
    VM Workstation的Unity Mode有什么用
    Office WORD EXCEL批量查找和替换技巧实例
    Visual Studio VS如何拷贝一个项目的窗体文件到另一个项目
  • 原文地址:https://www.cnblogs.com/sosi/p/3697134.html
Copyright © 2011-2022 走看看