【CodeVS1296】营业额统计
Description
Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。
Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:
该天的最小波动值 = min{|该天以前某一天的营业额-该天营业额|}
当最小波动值越大时,就说明营业情况越不稳定。
而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。
第一天的最小波动值为第一天的营业额。
Input
第一行为正整数n(n<=32767),表示该公司从成立一直到现在的天数,接下来的n行每行有一个正整数ai(ai<=1000000),表示第i天公司的营业额。
Output
输出文件仅有一个正整数,即每天最小波动值之和,小于231
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
题解
splay,求前驱和后继
CodeVS最后一个点超时
#include<iostream> #include<cstdio> using namespace std; const int MAXN = 40000; int num[MAXN]; int tr[MAXN][2]; int fa[MAXN]; int n,x,t1,t2,size,rt; long long ans; void rotate(int x,int &k) { int y = fa[x], z = fa[y], l, r; if (tr[y][0] == x) l = 0; else l = 1; r = 1^l; if (y == k) k = x; else { if (tr[z][0] == y) tr[z][0] = x; else tr[z][1] =x; } fa[x] = z; fa[y] = x; fa[tr[x][r]] = y; tr[y][l] = tr[x][r]; tr[x][r] = y; } void splay(int x,int &k) { int y,z; while (x != k) { y = fa[x] ,z = fa[y]; if (y != k) { if ((tr[z][0] == y) ^ (tr[y][0] == x)) rotate(x,k); else rotate(y,k); } rotate(x,k); } } void insert(int x,int &k,int last) { if (k == 0) { size ++; k = size; num[k] = x; fa[k] = last; splay(k,rt); return; } if (x>=num[k]) insert(x,tr[k][1],k); else insert(x,tr[k][0],k); } void before(int x,int k) { if (k == 0) return; if (num[k] <= x) { t1 = num[k]; before(x,tr[k][1]); } else before(x,tr[k][0]); } void after(int x,int k) { if (k == 0) return; if (num[k] >= x) { t2 = num[k]; after(x,tr[k][0]); } else after(x,tr[k][1]); } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%d",&x); if (!rt) { insert(x,rt,0); ans += x; } else { t1 = t2 = -1; before(x,rt); after(x,rt); if (t2 == -1) ans += (x-t1); else if (t1 == -1) ans += (t2-x); else ans += min(x-t1,t2-x); insert(x,rt,0); } } printf("%lld",ans); }