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
Key To Problem
平衡樹求前繼和後驅。
在平衡樹的分類中查到的題,就寫的平衡樹,但貌似線段樹也能做的樣子。。或許我在口胡。
Code
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100010
#define inf 0x3f3f3f3f
using namespace std;
struct node
{
int l,r,v,rnd,w,size;
};
node a[N];
int n,size,root,ans1,ans2,sum;
void updata(int k)
{
a[k].size=a[a[k].l].size+a[a[k].r].size+a[k].w;
}
void lturn(int &k)
{
int t=a[k].r;
a[k].r=a[t].l,a[t].l=k;
a[t].size=a[k].size,updata(k),k=t;
}
void rturn(int &k)
{
int t=a[k].l;
a[k].l=a[t].r,a[t].r=k;
a[t].size=a[k].size,updata(k),k=t;
}
void insert(int &k,int x)
{
if(k==0)
{
k=++size;
a[k].size=a[k].w=1,a[k].v=x,a[k].rnd=rand();
return ;
}
a[k].size++;
if(x==a[k].v)a[k].w++;
else if(x>a[k].v)
{
insert(a[k].r,x);
if(a[a[k].r].rnd<a[k].rnd)lturn(k);
}
else
{
insert(a[k].l,x);
if(a[a[k].l].rnd<a[k].rnd)rturn(k);
}
}
void query_before(int &k,int x)
{
if(k==0)return ;
if(x>=a[k].v)
ans1=a[k].v,query_before(a[k].r,x);
else
query_before(a[k].l,x);
}
void query_after(int &k,int x)
{
if(k==0)return ;
if(x<=a[k].v)
ans2=a[k].v,query_after(a[k].l,x);
else
query_after(a[k].r,x);
}
int main()
{
cin>>n>>sum;
insert(root,sum);
for(int i=2;i<=n;i++)
{
int x;
if(scanf("%d",&x)==EOF)x=0;
ans1=-inf,ans2=inf;
query_before(root,x);
query_after(root,x);
sum+=min(x-ans1,ans2-x);
insert(root,x);
}
cout<<sum<<endl;
return 0;
}