Description
营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。
Input
第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i天公司的营业额。
Output
输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。
Sample Input
6
5
1
2
5
4
6
Sample Output
12
又是一题treap的模板
每次加入元素时查找一下前驱后继即可。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
typedef long long ll;
struct node{
node*ch[2];
ll r,v,s;
node(ll x)
{
ch[0] = ch[1] = NULL;
r = rand(); s = 1; v = x;
}
int cmp(ll x)
{
if(x == v)return -1;
else return x > v ? 1 : 0;
}
void maintain()
{
s = 1;
if(ch[1]) s += ch[1]->s;
if(ch[0]) s += ch[0]->s;
}
}*root;
void rotate(node* &o,int d)
{
node* k = o->ch[d^1];
o->ch[d^1] = k->ch[d];
k->ch[d] = o;
o->maintain(); k->maintain();
o = k;
}
void insert(node* &o,ll x)
{
if(o == NULL) o = new node(x);
else
{
int d = o->cmp(x);
insert(o->ch[d],x);
if(o->ch[d]->r > o->r) rotate(o,d^1);
}
o->maintain();
}
int find(node *o,ll x)
{
while(o != NULL)
{
int d = o->cmp(x);
if(d == -1) return 1;
else o = o->ch[d];
}
return 0;
}
ll ans;
void ask_before(node *o,ll x)
{
if(o == NULL)return;
if(o->v < x)
{
ans = o->v;
ask_before(o->ch[1],x);
}else ask_before(o->ch[0],x);
}
void ask_after(node *o,ll x)
{
if(o == NULL)return;
if(o->v > x)
{
ans = o->v;
ask_after(o->ch[0],x);
} else ask_after(o->ch[1],x);
}
ll abss(ll x){return x > 0 ? x : -x;}
int main()
{
ll x,n,a,sum = 0;
ll inf = 1 << 30;
inf = inf * 32;
insert(root,inf);
insert(root,-inf);
scanf("%lld",&n);
scanf("%lld",&a);
sum = a;
insert(root,a);
for(int i = 2;i <= n;i++)
{
scanf("%lld",&a);
if(find(root,a) == 0)
{
insert(root,a);
ask_before(root,a);
x = abss(a - ans);
ask_after(root,a);
x = min(x,abss(ans - a));
sum += x;
}
}
printf("%lld",sum);
return 0;
}