bzoj1588 [HNOI2002]营业额统计
1588: [HNOI2002]营业额统计
Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 17931 Solved: 7391
[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
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裸题,每次找前驱和后继,找前驱的方法是在左子树中找最大的数(一直往右跳),后继就是在右子树中找最小的数(往左跳).需要注意的是每次插入完一个数都要将它翻到上面去.并且要更新根节点!
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 40010; struct node { int fa,left,right,v; }e[maxn]; int n,ans,Time,t,root = 1; bool flag = true; void turnr(int x) { int y = e[x].fa; int z = e[y].fa; e[y].left = e[x].right; if (e[x].right != -1) e[e[x].right].fa = y; e[x].fa = z; if (z != -1) { if (e[z].left == y) e[z].left = x; else e[z].right = x; } e[x].right = y; e[y].fa = x; } void turnl(int x) { int y = e[x].fa; int z = e[y].fa; e[y].right = e[x].left; if (e[x].left != -1) e[e[x].left].fa = y; e[x].fa = z; if (z != -1) { if (e[z].left == y) e[z].left = x; else e[z].right = x; } e[x].left = y; e[y].fa = x; } void splay(int x) { while (e[x].fa != -1) { int y = e[x].fa; int z = e[y].fa; if (z == -1) { if (x == e[y].left) turnr(x); else turnl(x); } else { if (e[z].left == y && e[y].left == x) { turnr(y); turnr(x); } else { if (e[z].right == y && e[y].right == x) { turnl(y); turnl(x); } else { if (e[z].left == y && e[y].right == x) { turnl(x); turnr(x); } else { turnr(x); turnl(x); } } } } } root = x; } void insert(int x,int y) { if (x == e[y].v) { flag = false; splay(y); return; } if (x < e[y].v) { if (e[y].left == -1) { e[y].left = ++Time; e[Time].left = e[Time].right = -1; e[Time].fa = y; e[Time].v = x; } else insert(x,e[y].left); } else { if (e[y].right == -1) { e[y].right = ++Time; e[Time].left = e[Time].right = -1; e[Time].fa = y; e[Time].v = x; } else insert(x,e[y].right); } } int findl(int x) { int y = e[x].left; if (y == -1) return y; while (e[y].right != -1) y = e[y].right; return y; } int findr(int x) { int y = e[x].right; if (y == -1) return y; while (e[y].left != -1) y = e[y].left; return y; } void solve(int x) { flag = true; insert(x,root); if (!flag) return; splay(Time); int p = findl(Time),q = findr(Time); int temp = 0x7fffffff; if (p != -1) temp = min(temp,abs(x - e[p].v)); if (q != -1) temp = min(temp,abs(x - e[q].v)); if (temp != 0x7fffffff) ans += temp; } int main() { scanf("%d",&n); scanf("%d",&t); ans += t; e[++Time].fa = -1; e[Time].left = -1; e[Time].right = -1; e[Time].v = t; for (int i = 2; i <= n; i++) { scanf("%d",&t); solve(t); } printf("%d\n",ans); return 0; }