1588: [HNOI2002]营业额统计
Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 3822 Solved: 1184
[ Submit][ Status][ Discuss]
Description
营业额统计Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。第一天的最小波动值为第一天的营业额。 输入输出要求
Input
第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个正整数 ,表示第i天公司的营业额。
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
Source
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int N, M, rt, cnt;
const int MN = 1100010;
int ch[MN][2], pre[MN], val[MN];
int newnode ( int x, int p, int v ) {///创建新节点
ch[x][0] = ch[x][1] = 0, pre[x] = p;
val[x] = v;///节点上的数值
return x;
}
void rotate ( int x, int f ) {///把第k位的数转到f下边
///类似SBT,要把其中一个分支先给父节点
int y = pre[x], z = pre[y];
ch[y][!f] = ch[x][f], pre[ ch[x][f] ] = y;
ch[x][f] = y, pre[ y ] = x;
pre[x] = z;
if ( z ) ch[z][ ch[z][1] == y ] = x; ///如果父节点不是根结点,则要和父节点的父节点连接起来
}
int insert ( int &x, int p, int v ) {///插入
if ( x == 0 ) {
return newnode ( x = cnt++, p, v );
} else {
return insert ( ch[x][ val[x] < v ], x, v );
}
}
int splay ( int x, int f ) {///Splay调整,将根为r的子树调整为f
while ( pre[x] != f ) {
int y = pre[x], z = pre[y];
if ( z == f ) rotate ( x, ch[y][0] == x );
else {
int f = ( ch[z][1] == y );
if ( ch[y][!f] == x ) { ///两个方向不同,则先左旋再右旋
rotate ( x, f ), rotate ( x, !f );
} else { ///两个方向相同,相同方向连续两次
rotate ( y, !f ), rotate ( x, !f );
}
}
}
if ( f == 0 ) rt = x; ///更新根结点
}
int findMax ( int rt ) {
return ch[rt][1] == 0 ? rt : findMax ( ch[rt][1] );
}
int findMin ( int rt ) {
return ch[rt][0] == 0 ? rt : findMin ( ch[rt][0] );
}
void print ( int rt ) {
if ( rt == 0 ) return;
print ( ch[rt][0] );
printf ( "%4d", val[rt] );
print ( ch[rt][1] );
}
int main ()
{
// freopen("//media/学习/ACM/input.txt","r",stdin);
while ( scanf ( "%d", &N ) == 1 ) {
ch[0][1] = ch[0][0] = val[0] = pre[0] = 0;///
cnt = 1, rt = 0;
int sum = 0;
int mi, ma;
for ( int i = 1; i <= N; ++ i ) {
if(scanf("%d",&M)==EOF) M=0;
int pos = insert ( rt, 0, M );
splay ( pos, 0 );
if ( i>1 && ch[rt][1] == 0 ) mi = -0x5ffffff;
else mi = val[ findMin ( ch[rt][1] ) ];
if ( i>1 && ch[rt][0] == 0 ) ma = -0x5ffffff;
else ma = val[ findMax ( ch[rt][0] ) ];
if(i==1)sum=abs(M);
else sum += min ( abs( M-mi ), abs( M-ma ) );
//cout<<"step "<<i<<" "<<sum<<endl;
}
//cout<<"result : ";
printf ( "%d\n", sum);
}
return 0;
}