首页 > 代码库 > BZOJ 1588 营业额统计 Splay

BZOJ 1588 营业额统计 Splay

主要操作为Splay中插入节点,查找前驱和后继节点。

   1:  #include <cstdio>
   2:  #include <iostream>
   3:  #include <cmath>
   4:  using namespace std;
   5:  #define MaxL 100005
   6:  #define INF 0x7ffffff
   7:  #define keyTree   sp[sp[root].child[1]].child[0]
   8:   
   9:  struct SplayTreeNode
  10:  {
  11:      int parent, child[2];   // parent and child[0] left child[1] right
  12:      int sz, val;  // sz 表示当前节点为根的子树总节点个数.  val表示当前节点的键值。
  13:      int lazy;     //  延迟标记
  14:      long long sum;   // 以x为根节点的子树的所有的和
  15:  };
  16:   
  17:  int num[MaxL];
  18:  struct SpalyTree
  19:  {
  20:      SplayTreeNode sp[MaxL];   // save space
  21:      int gc[MaxL];   // Garbage Collection idx
  22:      int root;  // root idx
  23:      int idx;   // Forward allocate tree
  24:      int idxrev; // garbage allocated nodes used for next allocation priority
  25:   
  26:      /*
  27:           A                        B
  28:         /   \    R(B,RR)->       /   \
  29:        B     C    <-R(A,LL)     D     A
  30:       / \                            /  \
  31:      D   E                          E    C
  32:      */
  33:      void Rotate(int x,int f)   // f ==0 l rot,1 r rot
  34:      {
  35:          int y = sp[x].parent;
  36:          PushDown(y);
  37:          PushDown(x);
  38:          sp[y].child[!f] = sp[x].child[f];
  39:          sp[sp[x].child[f]].parent = y;
  40:          sp[x].parent = sp[y].parent;
  41:          if(sp[x].parent)
  42:              sp[sp[y].parent].child[ sp[sp[y].parent].child[1] == y]= x;
  43:          sp[x].child[f] = y;
  44:          sp[y].parent = x;
  45:          PushUp(y);
  46:      }
  47:   
  48:      // x to be the child of goal, x and goal are key
  49:      void Splay(int x, int goal)
  50:      {
  51:          PushDown(x);
  52:          while(sp[x].parent != goal)
  53:          {
  54:              if(sp[sp[x].parent].parent == goal)
  55:                  Rotate(x, sp[sp[x].parent].child[0] == x);
  56:              else
  57:              {
  58:                  int y = sp[x].parent, z = sp[y].parent;
  59:                  int f = sp[z].child[0] == y;
  60:                  if(sp[y].child[f] == x)
  61:                      Rotate(x,!f), Rotate(x,f);
  62:                  else
  63:                      Rotate(y,f), Rotate(x,f);
  64:              }
  65:          }
  66:          PushUp(x);
  67:          if(goal == 0) root = x;
  68:      }
  69:   
  70:      //  把第k个的数转到goal下边,一般用来调整区间, 返回其key 键
  71:      int RotateTo(int k, int goal)
  72:      {
  73:          int x = root;
  74:          PushDown(x);
  75:          while(sp[sp[x].child[0]].sz !=k)
  76:          {
  77:              if( k< sp [ sp[x].child[0] ].sz)
  78:                  x = sp[x].child[0];
  79:              else
  80:              {
  81:                  k -= sp[sp[x].child[0]].sz +1;
  82:                  x = sp[x].child[1];
  83:              }
  84:              PushDown(x);
  85:          }
  86:          cout<<"Rotate "<<x<<" goal "<<goal<<endl;
  87:          Splay(x, goal);
  88:          return x;
  89:      }
  90:   
  91:      // insert a value, return the key
  92:      // first find the key, then insert a value.
  93:      // 不重复插入
  94:      pair<int,bool> Insert(int val)
  95:      {
  96:          int p = root;
  97:          while( sp[p].val == val || sp[p].child[ sp[p].val < val ])
  98:          {
  99:              if(sp[p].val == val)
 100:              {
 101:                  Splay(p, 0);
 102:                  return make_pair(p,false);
 103:              }
 104:              p = sp[p].child[sp[p].val < val];
 105:          }
 106:          int x = NewNode(sp[p].child[sp[p].val < val], val);
 107:          sp[x].parent = p;
 108:          Splay(x, 0);
 109:          return make_pair(x, true);
 110:      }
 111:   
 112:      int findPrefix(int x)
 113:      {
 114:          Splay(x,0);
 115:          int p = sp[x].child[0];
 116:          if(p)
 117:          {
 118:              while(sp[p].child[1])
 119:                  p = sp[p].child[1];
 120:          }
 121:          return p;
 122:      }
 123:   
 124:      int findSuffix(int x)
 125:      {
 126:          Splay(x, 0);
 127:          int p = sp[x].child[1];
 128:          if(p)
 129:          {
 130:              while(sp[p].child[0])
 131:                  p = sp[p].child[0];
 132:          }
 133:          return p;
 134:      }
 135:   
 136:   
 137:      int NewNode(int &x, int c)
 138:      {
 139:          if( idxrev) x = gc[--idxrev];
 140:          else  x = ++idx;
 141:          sp[x].child[1] = 0, sp[x].child[0] = 0, sp[x].parent = 0;
 142:          sp[x].sz = 1;
 143:          sp[x].val = sp[x].sum = c;
 144:          sp[x].lazy = 0;
 145:          return x;
 146:      }
 147:   
 148:      //把以x为祖先结点(x 也算)删掉放进内存池,回收内存
 149:      void eraseSubTree(int x)
 150:      {
 151:          int father = sp[x].parent;
 152:          int head = idxrev , tail = idxrev;
 153:          for (gc[tail++] = x ; head < tail ; head ++)
 154:          {
 155:              idxrev++;
 156:              if( sp[gc[head]].child[0]) gc[tail++] = sp[gc[head]].child[0];
 157:              if( sp[gc[head]].child[1]) gc[tail++] = sp[gc[head]].child[1];
 158:          }
 159:          sp[father].child[ sp[father].child[1] == x] = 0;
 160:          PushUp(father);
 161:      }
 162:   
 163:      void makeTree(int &x, int l, int r, int parent)
 164:      {
 165:          if(l > r) return ;
 166:          int m = (l+r)>>1;
 167:          NewNode(x,num[m]);
 168:          makeTree(sp[x].child[0], l, m-1, x);
 169:          makeTree(sp[x].child[1], m+1, r, x);
 170:          sp[x].parent = parent;
 171:          PushUp(x);
 172:      }
 173:      void Init(int n)
 174:      {
 175:          idx = idxrev =  0;
 176:          root = 0;
 177:          sp[0].child[0] = sp[0].child[1] = sp[0].parent  = 0;
 178:          sp[0].sz = sp[0].lazy = sp[0].sum = 0;
 179:      }
 180:   
 181:      void Travel(int x)
 182:      {
 183:          if(x)
 184:          {
 185:              Travel( sp[x].child[0]);
 186:              printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d\n",x, sp[x].child[0],sp[x].child[1],sp[x].parent,sp[x].sz,sp[x].val);
 187:              Travel( sp[x].child[1]);
 188:          }
 189:      }
 190:   
 191:      //Problem Specific Function
 192:      void PushUp(int x )
 193:      {
 194:          sp[x].sz = 1 + sp[sp[x].child[0]].sz + sp[sp[x].child[1]].sz;
 195:          sp[x].sum = sp[x].lazy + sp[x].val + sp[sp[x].child[0]].sum + sp[sp[x].child[1]].sum;
 196:      }
 197:   
 198:      void PushDown(int x)
 199:      {
 200:          if(sp[x].lazy)
 201:          {
 202:              sp[x].val += sp[x].lazy;
 203:              sp[sp[x].child[0]].lazy += sp[x].lazy;
 204:              sp[sp[x].child[1]].lazy += sp[x].lazy;
 205:              sp[sp[x].child[0]].sum += (long long) sp[ sp[x].child[0]].sz * sp[x].lazy;
 206:              sp[sp[x].child[1]].sum += (long long) sp[ sp[x].child[1]].sz * sp[x].lazy;
 207:              sp[x].lazy = 0;
 208:          }
 209:      }
 210:   
 211:      void update(int l, int r, int c )
 212:      {
 213:          RotateTo(l-1,0);
 214:          RotateTo(r+1,root);
 215:          sp[keyTree].lazy += c;
 216:          sp[keyTree].sum += (long long) c * sp[keyTree].sz;
 217:      }
 218:   
 219:      // query for the interval [l,r]
 220:      void query(int l, int r)
 221:      {
 222:          RotateTo(l-1,0);
 223:          RotateTo(r+1,root);
 224:  //        int keyTree =  sp [sp[root].child[1] ].child[0];
 225:          printf("%lld\n",sp[keyTree].sum);
 226:      }
 227:  } spt;
 228:   
 229:  int abs(int x)
 230:  {
 231:      if(x < 0) return -x;
 232:      else return x;
 233:  }
 234:  int main()
 235:  {
 236:   
 237:      //freopen("1.txt","r",stdin);
 238:      int n,m;
 239:      cin>>n;
 240:      m = 0;
 241:      for(int i=0; i<n; i++)
 242:          scanf("%d",&num[i]);
 243:      spt.Init(0);
 244:      int ret = 0;
 245:      while(m!=n)
 246:      {
 247:          pair<int,bool> state = spt.Insert(num[m]);
 248:          if(state.second != 0)
 249:          {
 250:              int pre = spt.findPrefix(state.first);
 251:              int nxt = spt.findSuffix(state.first);
 252:              int ans = INF;
 253:              if(pre)
 254:                  ans = abs(num[m] - spt.sp[pre].val);
 255:              if(nxt)
 256:              {
 257:                  int x = abs(num[m] - spt.sp[nxt].val);
 258:                  ans = std::min(ans, x );
 259:              }
 260:   
 261:              if(pre == 0 && nxt == 0) ans = num[0];
 262:  //            cout<<num[m]<<" "<<pre<<" "<<nxt<<" "<<ans<<endl;
 263:              ret += ans;
 264:          }
 265:          m++;
 266:      }
 267:      cout<<ret<<endl;;
 268:      return 0;
 269:  }
 270:   
 271:   
 272:   
<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>