1588: [HNOI2002]营业额统计
Time Limit: 5 Sec
Memory Limit: 162 MB
Submit: 5783
Solved: 1859
Description
营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。 输入输出要求
Input
第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个正整数 ,表示第i天公司的营业额。
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
Source
1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013/8/24 10:57:20 4 File Name :F:\2013ACM练习\专题学习\splay_tree_2\营业额统计.cpp 5 ************************************************ */ 6 7 #include <stdio.h> 8 #include <string.h> 9 #include <iostream> 10 #include <algorithm> 11 #include <vector> 12 #include <queue> 13 #include <set> 14 #include <map> 15 #include <string> 16 #include <math.h> 17 #include <stdlib.h> 18 #include <time.h> 19 using namespace std; 20 21 #define Key_value ch[ch[root][1]][0] 22 const int MAXN = 1000010; 23 int pre[MAXN],ch[MAXN][2],key[MAXN]; 24 int root,tot1; 25 26 int s[MAXN],tot2;//内存池 27 28 void NewNode(int &r,int father,int k) 29 { 30 if(tot2) r = s[tot2--];//取的时候是tot2--,存的时候就要是++tot2 31 else r = ++tot1;//这个必须是++tot1 32 pre[r] = father; 33 ch[r][0] = ch[r][1] = 0; 34 key[r] = k; 35 } 36 //初始化 37 void Init() 38 { 39 root = tot1 = tot2 = 0; 40 ch[root][0] = ch[root][1] = key[root] = pre[root] = 0; 41 } 42 //旋转,0为左旋,1为右旋 43 void Rotate(int x,int kind) 44 { 45 int y = pre[x]; 46 ch[y][!kind] = ch[x][kind]; 47 pre[ch[x][kind]] = y; 48 if(pre[y]) 49 ch[pre[y]][ch[pre[y]][1]==y] = x; 50 pre[x] = pre[y]; 51 ch[x][kind] = y; 52 pre[y] = x; 53 } 54 //Splay调整,将r结点调整到goal下面 55 void Splay(int r,int goal) 56 { 57 while(pre[r] != goal) 58 { 59 if(pre[pre[r]]==goal) 60 Rotate(r,ch[pre[r]][0] ==r); 61 else 62 { 63 int y = pre[r]; 64 int kind = ch[pre[y]][0]==y; 65 if(ch[y][kind] == r) 66 { 67 Rotate(r,!kind); 68 Rotate(r,kind); 69 } 70 else 71 { 72 Rotate(y,kind); 73 Rotate(r,kind); 74 } 75 } 76 } 77 if(goal == 0)root = r; 78 } 79 80 void Insert(int k)//插入一个值为k的结点(有重复插入) 81 { 82 int r = root; 83 if(r == 0) 84 { 85 NewNode(root,0,k); 86 return; 87 } 88 while(ch[r][key[r]<k]) 89 r = ch[r][key[r]<k]; 90 NewNode(ch[r][key[r]<k],r,k); 91 Splay(ch[r][key[r]<k],0);//转到根部 92 } 93 //找前驱 94 int Get_pre(int r) 95 { 96 if(ch[r][0] == 0)return -1;//不存在 97 r = ch[r][0]; 98 while(ch[r][1])r = ch[r][1]; 99 return r; 100 } 101 //找后继 102 int Get_next(int r) 103 { 104 if(ch[r][1] == 0)return -1; 105 r = ch[r][1]; 106 while(ch[r][0])r = ch[r][0]; 107 return r; 108 } 109 const int INF = 0x3f3f3f3f; 110 111 int main() 112 { 113 //freopen("in.txt","r",stdin); 114 //freopen("out.txt","w",stdout); 115 int n; 116 while(scanf("%d",&n) == 1) 117 { 118 Init(); 119 int a; 120 int ans = 0; 121 for(int i = 0;i < n;i++) 122 { 123 if(scanf("%d",&a) == EOF) a= 0; 124 Insert(a); 125 if(i == 0) 126 ans += a; 127 else 128 { 129 int tmp = INF; 130 int t1 = Get_pre(root); 131 if(t1 != -1) 132 tmp = min(tmp,key[root] - key[t1]); 133 int t2 = Get_next(root); 134 if(t2 != -1) 135 tmp = min(tmp,key[t2] - key[root]); 136 ans += tmp; 137 } 138 } 139 printf("%d\n",ans); 140 } 141 return 0; 142 }