bzoj 1588 平衡树 splay

1588: [HNOI2002]营业额统计

Time Limit: 5 Sec  Memory Limit: 162 MB
Submit: 15446  Solved: 6076
[Submit][Status][Discuss]

Description

营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。 ? 输入输出要求

Input

第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i

天公司的营业额。

天数n<=32767,

每天的营业额ai <= 1,000,000。

最后结果T<=2^31

Output

输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。

Sample Input

6
5
1
2
5
4
6

Sample Output

12

HINT

结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12

该题数据bug已修复.----2016.5.15

题意:每次插入一个数,在数列中找到一个数,使得该数与插入的数的差值最小 差值取绝对值 求和输出

题解:平衡树入门 通过旋转 在不影响树的结构的情况下 保持最优的操作效率 splay

  1 #include <bits/stdc++.h>
  2 #define ll  long
  3 using namespace  std;
  4 ll tim=0,n,root,sum=0;
  5 bool flag;
  6 struct node
  7 {
  8     ll father,left,right,data;
  9 } tree[100005];
 10  ll mins(ll aaa, ll bbb)
 11 {
 12     if(aaa<bbb)
 13         return aaa;
 14     else
 15         return bbb;
 16 }
 17  ll abss(ll x)
 18 {
 19     if(x<0)
 20         return -x;
 21     else
 22         return x;
 23 }
 24 void rightrotate(ll x)
 25 {
 26     ll y=tree[x].father;
 27     ll z=tree[y].father;
 28     tree[y].left=tree[x].right;
 29     if(tree[x].right!=-1)
 30     {
 31         tree[tree[x].right].father=y;
 32     }
 33     tree[x].father=z;
 34     if(z!=-1)
 35     {
 36         if(tree[z].left==y) tree[z].left=x;
 37         else tree[z].right=x;
 38     }
 39     tree[x].right=y;
 40     tree[y].father=x;
 41 }
 42 void leftrotate(ll x)
 43 {
 44     ll y=tree[x].father;
 45     ll z=tree[y].father;
 46     tree[y].right=tree[x].left;
 47     if(tree[x].left!=-1)
 48     {
 49         tree[tree[x].left].father=y;
 50     }
 51     tree[x].father=z;
 52     if(z!=-1)
 53     {
 54         if(tree[z].left==y) tree[z].left=x;
 55         else tree[z].right=x;
 56     }
 57     tree[x].left=y;
 58     tree[y].father=x;
 59 }
 60 void splay(ll x)
 61 {
 62     while(tree[x].father!=-1)
 63     {
 64         ll y=tree[x].father;
 65         ll z=tree[y].father;
 66         if(z==-1)
 67         {
 68             if(tree[y].left==x) rightrotate(x);
 69             else leftrotate(x);
 70         }
 71         else
 72         {
 73             if(tree[z].left==y&&tree[y].left==x)
 74             {
 75                 rightrotate(y);
 76                 rightrotate(x);
 77             }
 78             else if(tree[z].left==y&&tree[y].right==x)
 79             {
 80                 leftrotate(x);
 81                 rightrotate(x);
 82             }
 83             else if(tree[z].right==y&&tree[y].right==x)
 84             {
 85                 leftrotate(y);
 86                 leftrotate(x);
 87             }
 88             else
 89             {
 90                 rightrotate(x);
 91                 leftrotate(x);
 92             }
 93         }
 94     }root=x;
 95 }
 96 ll qq(ll x)
 97 {
 98     ll y=tree[x].left;
 99     if(y==-1) return y;
100     while(tree[y].right!=-1) y=tree[y].right;
101     return y;
102 }
103 ll hj(ll x)
104 {
105     ll y=tree[x].right;
106     if(y==-1) return y;
107     while(tree[y].left!=-1) y=tree[y].left;
108     return y;
109 }
110 int BST_insert(ll dat,ll x)
111 {
112     if(dat==tree[x].data)
113     {
114         flag=false ;
115         splay(x);
116         return 0;
117     }
118     if(dat<tree[x].data)
119     {
120         if(tree[x].left==-1)
121         {
122             tree[x].left=tim;
123             tree[tim].father=x;
124             tree[tim].left=tree[tim].right=-1;
125             tree[tim].data=dat;
126         }
127         else
128             BST_insert(dat,tree[x].left);
129     }
130     else
131     {
132         if(tree[x].right==-1)
133         {
134             tree[x].right=tim;
135             tree[tim].father=x;
136             tree[tim].left=tree[tim].right=-1;
137             tree[tim].data=dat;
138         }
139         else
140             BST_insert(dat,tree[x].right);
141     }
142 }
143 ll insert1(ll dat)
144 {
145     flag=true;
146     tim++;
147     BST_insert(dat,root);
148     if(flag==false) return 0;
149     splay(tim);
150     ll q=qq(tim);
151     ll h=hj(tim);
152     ll minx=2000000000;
153     if(q!=-1) minx=mins(minx,abss(tree[q].data-dat));
154     if(h!=-1) minx=mins(minx,abss(tree[h].data-dat));
155     sum+=minx;
156 }
157 int main()
158 {
159     int n;
160     ll aa=0;
161     while(scanf("%d",&n)!=-1)
162     {
163     sum=0;
164     tim=0;
165     scanf("%ld",&aa);
166     sum=aa;
167     tim++;
168     tree[tim].father=-1;
169     tree[tim].left=tree[tim].right=-1;
170     tree[tim].data=aa;
171     root=tim;
172     for(ll i=1; i<n; i++)
173     {
174         aa=0;
175         scanf("%ld",&aa);
176         insert1(aa);
177     }
178     printf("%ld\n",sum);
179     }
180     return 0;
181 }
时间: 2024-08-05 10:58:53

bzoj 1588 平衡树 splay的相关文章

BZOJ 1588:splay tree

刚学习的splay tree.照着大神的代码敲了敲,理解了个大概 很好用的数据结构,可以用来维护数列 学习时建议先看看SBT,这样可以更好地理解“旋转” #include"cstdio" #include"queue" #include"cmath" #include"stack" #include"iostream" #include"algorithm" #include"

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 SplayTree

【BZOJ3224】Tyvj 1728 普通平衡树 Splay

Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)6. 求x的后继(后继定义为大于x,且最小的数) Input 第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6) Output 对于操作3,4,5,6每行输

BZOJ 1588: [HNOI2002]营业额统计 双向链表

BZOJ 1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 512 MBSubmit: 9619  Solved: 3287 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1588 Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来

bzoj 1588 [HNOI2002] 营业额统计 链表和Splay

来自HNOI 2002营业额的统计一题,这题以前是用链表水过的,最近看见许多splay的题,赶紧张一下知识. 题目大意就是对于一个序列,输出每个元素与它之前元素的差的最小值的和.先说链表的方法吧. 大概就是sort一下,记录每个点的rank.然后链表一下,很好理解,复杂度nlogn,瓶颈在于排序. #include<cstdio> #include<algorithm> #include<iostream> using namespace std; struct nod

BZOJ 1588:营业额统计(Splay)

http://www.lydsy.com/JudgeOnline/problem.php?id=1588 题意:中文题意. 思路:每一个点每一个点插入Splay,然后插入新的一个点之后,查这个节点的前驱和后继,即左子树最右边的点和右子树最左边的点.然后再从两个点中取个差值较小的就是答案了.要注意Rotate的时候一些细节(要给 rt 的父亲的父亲更新其孩子的值),还有Splay的细节:如果 rt 和 父节点都是要旋转相同方向,应该先旋转父亲节点再旋 rt,如果旋转不同方向就都是旋 rt. 1 #

bzoj 3223 文艺平衡树 Splay 打标志

是NOI2003Editor的一个子任务 1 #include <cstdio> 2 #include <vector> 3 #define maxn 100010 4 using namespace std; 5 6 struct Splay { 7 int pre[maxn], son[maxn][2], siz[maxn], rev[maxn], root; 8 9 void update( int nd ) { 10 siz[nd] = siz[son[nd][0]]+si

bzoj 1588 splay模板题

用晚自习学了一下splay模板,没想象中那么难,主要是左旋和右旋可以简化到一个函数里边,减少代码长度... 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 33333 6 #define inf 0x3f3f3f3f 7 #define lc(x) ch[(x)][0] 8 #define rc(x) ch[(x)

BZOJ 1588: [HNOI2002]营业额统计 双向链表 / splay / treap

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