bzoj1588
Description
Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。
Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:
该天的最小波动值=min{|改天以前某天营业额−改天营业额|}
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
题解
在splay中查找前驱和后继即可。
#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 33000, inf = 1 << 30;
struct Splay{
int a;
Splay *c[2], *f;
int d(){return f->c[1] == this;}
void sc(Splay* x, int d){(c[d] = x)->f = this;}
};
Splay *null = new Splay();
Splay *root = new Splay();
void rotate(Splay *x){
int d = x->d();
Splay* p = x->f;
p->sc(x->c[!d], d);
if(p == root) x->f = null, root = x;
else p->f->sc(x, p->d());
x->sc(p, !d);
}
void splay(Splay *x){
for(Splay* y; x != root; ){
y = x->f;
if(y != root) (x->d() ^ y->d()) ? rotate(x): rotate(y);
rotate(x);
}
}
void insert(Splay *q){
Splay *p = root;
for(;;){
int d = q->a > p->a;
if(p->c[d] != null) p = p->c[d];
else {p->sc(q, d), splay(q); break;}
}
}
int n, ans;
void init(){
scanf("%d", &n);
}
void work(){
int x; Splay *q, *tmp;
null->a = inf;
scanf("%d", &x);
q = new Splay();
q->a = x; q->c[0] = q->c[1] = q->f = null;
root = q;
ans += x;
for(int i = 1; i < n; i++){
scanf("%d", &x);
q = new Splay();
q->a = x; q->c[0] = q->c[1] = q->f = null;
insert(q);
int t1 = inf, t2 = inf;
if(q->c[0] != null){
tmp = q->c[0];
while(null != tmp->c[1]) tmp = tmp->c[1];
t1 = tmp->a;
}
if(q->c[1] != null){
tmp = q->c[1];
while(null != tmp->c[0]) tmp = tmp->c[0];
t2 = tmp->a;
}
ans += min(abs(x - t1), abs(t2 - x));
}
printf("%d\n", ans);
}
int main(){
freopen("turnover.in", "r", stdin);
freopen("turnover.out", "w", stdout);
init();
work();
}