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:   

.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; }

BZOJ 1588 营业额统计 Splay,布布扣,bubuko.com

时间: 2024-08-26 22:52:08

BZOJ 1588 营业额统计 Splay的相关文章

BZOJ 1588 营业额统计

Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题.经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大

bzoj 1588营业额统计(HNOI 2002)

http://www.lydsy.com/JudgeOnline/problem.php?id=1588 我的第一颗splay, bottom-up的数组实现. 题意就是给你一组数,求每个数与在其前面且与其最相近的数的差值的绝对值. 考虑splay二叉搜索树的特性,每新插入一个节点,比它小且最靠近它的数在是左子树中的最大值,另一半同理. 代码借鉴自:http://blog.csdn.net/ACM_cxlove?viewmode=contents 1 #include <cstdio> 2 #

BZOJ1588 营业额统计 splay tree

最基本的平衡树操作吧,第一次学splay的可以做一下 只需要插入,删除,旋转,求前驱,后继这5个操作吧 不喜欢用指针,用数组写的 <span style="color:#00cccc;">//HNOI2002营业额统计 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define INF 1<<30 #define

【BZOJ-1588】营业额统计 Splay

1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 12485  Solved: 4508[Submit][Status][Discuss] Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其

BZOJ1588 [HNOI2002]营业额统计 splay模板

1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 16189  Solved: 6482 [Submit][Status][Discuss] Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者

BZOJ1588 HNOI2002 营业额统计 [Splay入门题]

[HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 4128  Solved: 1305 Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其他情况的时候,营业 额会出现一定的波动,当然一定的波动是能够接受

1588: [HNOI2002]营业额统计 splay tree

//http://www.lydsy.com/JudgeOnline/problem.php?id=1588 //题意:每读入一个数,在前面输入的数中找到一个与该数相差最小的一个,把所有的差值绝对值加起来并输出 1 #include "bits/stdc++.h" 2 using namespace std; 3 const int maxn = 100010; 4 const int INF = 0x3f3f3f3f; 5 struct SplayTreeNode 6 { 7 int

HYSBZ 1588 营业额统计 (Splay)

题意:给出一个公司每一天的营业额,求每天的最小波动值之和.该天的最小波动值= min { 绝对值| 该天以前某一天的营业额-该天的营业额 | }.第一天的最小波动值就是其自己. 思路:Splay伸展树的入门题,仅有splay,insert,rotate这三个主要的函数而已. 将一个数字(营业额)插入树中,并把其splay到根位置,然后其前驱和后继中离它较近的一个用来求最小波动值.注意可能没有前驱/后继.对第一个数特别处理. 注意:此题的数据有缺陷,读入营业额之前先将变量清零. 1 #includ

HYSBZ 1588 营业额统计

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1588 题意:详见题面,中文 思路:平衡树的模板题. 可用Treap,Splay,Scapegoat Tree. [替罪羊树代码] #define _CRT_SECURE_NO_DEPRECATE #include<stdio.h> #include<string.h> #include<cstring> #include<algorithm> #in