BZOJ 1588 [HNOI 2002] 营业额统计 Splay
Description
营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。第一天的最小波动值为第一天的营业额。
Input
第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i天公司的营业额。
Output
输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。
Sample Input
6
5
1
2
5
4
6Sample Output
12
HINT
结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12
此题数据有问题,详见讨论版http://www.lydsy.com/JudgeOnline/wttl/wttl.php?pid=1588
Splay不带删除,只询问前驱和后继即可。每次取当天营业额与前驱的差和与后继的差的最小值相加,即使所求答案。
不过题的数据好像有问题,不过将每天的营业额的初始值设为0,好像就没有问题了…【来自红太阳DQS的教导】 %%%
但是这题我CE了,原因不明,不过把cmath改成algorithm就A了……
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int SZ = 1000010;
const int INF = 1000000010;
struct node
{
node *ch[2], *f;
int sz, cnt, v;
void maintain()
{
sz = cnt + ch[0] -> sz + ch[1] -> sz;
}
int cmp(int x)
{
if(x == v) return -1;
return x < v ? 0 : 1;
}
int dir()
{
return f -> ch[1] == this;
}
int setc(node *x, int d)
{
(ch[d] = x) -> f = this;
}
}T[SZ], *root, *null;
int Tcnt = 0;
node* newnode(int x, node *f)
{
node *k = T + (Tcnt ++);
k -> v = x;
k -> ch[0] = k -> ch[1] = null;
k -> sz = k -> cnt = 1;
k -> f = f;
return k;
}
void rotate(node *p)
{
node *fa = p -> f;
int d = p -> dir();
fa -> f -> setc(p, fa -> dir());
fa -> setc(p -> ch[d ^ 1], d); fa -> maintain();
p -> setc(fa ,d ^ 1); p -> maintain();
if(fa == root) root = p;
}
void splay(node *p, node *rt = null)
{
while(p -> f != rt)
{
if(p -> f -> f == rt)
rotate(p);
else
{
if(p -> dir() == p -> f -> dir())
rotate(p -> f), rotate(p);
else
rotate(p), rotate(p);
}
}
p -> maintain();
}
void insert(node *p, int x)
{
if(root == null)
{
root = newnode(x, null);
return ;
}
while(p != null)
{
p -> sz ++;
int d = p -> cmp(x);
if(d == -1)
{
p -> cnt ++;
break;
}
if(p -> ch[d] == null)
{
p -> ch[d] = newnode(x, p);
p = p -> ch[d];
break;
}
p = p -> ch[d];
}
splay(p);
}
int ask_pre(node *p, int x)
{
int ans = INF;
while(p != null)
{
if(p -> v <= x)
ans = p -> v, p = p -> ch[1];
else
p = p -> ch[0];
}
return ans;
}
int ask_suf(node *p, int x)
{
int ans = INF;
while(p != null)
{
if(p -> v >= x)
ans = p -> v, p = p -> ch[0];
else
p = p -> ch[1];
}
return ans;
}
void init()
{
null = newnode(-INF, null);
null -> sz = null -> cnt = 0;
root = null;
}
int main()
{
init();
int n, ans = 0;
scanf("%d", &n);
while(n --)
{
int x = 0;
scanf("%d", &x);
if(root -> sz)
ans += min(abs(x - ask_pre(root, x)), abs(x - ask_suf(root, x)));
else
ans = x;
insert(root, x);
}
printf("%d", ans);
return 0;
}