zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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:   
  • 相关阅读:
    项目上线之期初数据调整
    系统升级时,数据库脚本执行注意事项,血的教训
    数据精度问题的处理
    系统发布说明文档
    SQLServer中数据库文件的存放方式,文件和文件组
    数据库的持续集成和版本控制
    SQL Server 远程链接服务器详细配置【转载】
    批处理中的IF ERRORLEVEL
    asp.net用url重写URLReWriter实现任意二级域名
    关于excel导入access问题(已解决)
  • 原文地址:https://www.cnblogs.com/sosi/p/3700937.html
Copyright © 2011-2022 走看看