HYSBZ 1588 营业额统计

本文介绍了一个营业额统计的问题,通过使用Splay树(伸展树)来高效地计算每天的最小波动值,进而评估公司的营业稳定性。文章提供了完整的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


1588: [HNOI2002]营业额统计

Time Limit: 5 Sec   Memory Limit: 162 MB
Submit: 14859   Solved: 5775
[ Submit][ Status][ Discuss]

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


该题数据bug已修复.----2016.5.15

Source

[ Submit][ Status][ Discuss]

题意:依次插入n个数,每次求出插入数和之前的数的最小差,并求和。

思路:貌似是splay裸题,首次写的平衡树,看了好久才看得懂原理的我实在太渣了。代码如下:

#include<cstdio>  
#include<algorithm>  
#include<cstring>  
#include<iostream>  
#include<cmath>  
#include<queue>  
#include<functional>  
typedef long long LL;
using namespace std;
#define maxn 100005
#define ll l,mid,now<<1  
#define rr mid+1,r,now<<1|1  
#define lson l1,mid,l2,r2,now<<1  
#define rson mid+1,r1,l2,r2,now<<1|1  
#define inf 0x3f3f3f3f  
const int mod = 1e9 + 7;
int value[maxn], root, len, pre[maxn], ch[maxn][2];
void newnode(int &now, int fa, int v){
	now = ++len;
	pre[now] = fa;
	value[now] = v;
	ch[now][0] = ch[now][1] = 0;
}
void rotate(int x, int kind){//1右旋 0左旋
	int fa = pre[x];
	ch[fa][!kind] = ch[x][kind];
	pre[ch[x][kind]] = fa;
	if (pre[fa])
		ch[pre[fa]][ch[pre[fa]][1] == fa] = x;
	pre[x] = pre[fa];
	pre[fa] = x;
	ch[x][kind] = fa;
}
void splay(int r, int target){
	while (pre[r] != target){
		if (pre[pre[r]] == target)
			rotate(r, ch[pre[r]][0] == r);
		else{
			int fa = pre[r];
			int kind = ch[pre[fa]][0] == fa;
			if (r == ch[fa][kind]){
				rotate(r, !kind);
				rotate(r, kind);
			}
			else{
				rotate(fa, kind);
				rotate(r, kind);
			}
		}
	}
	if (!target)
		root = r;
}
bool insert(int v){
	int r = root;
	while (ch[r][v > value[r]]){
		if (v == value[r]){
			splay(r,0);
			return false;
		}
		r = ch[r][v > value[r]];
	}
	if (v == value[r]){
		splay(r, 0);
		return false;
	}
	newnode(ch[r][v > value[r]], r, v);
	splay(ch[r][v > value[r]], 0);
	return true;
}
int getpre(int x){
	int now = ch[x][0];
	if (!now)
		return -1;
	while (ch[now][1])
		now = ch[now][1];
	return now;
}
int getnext(int x){
	int now = ch[x][1];
	if (!now)
		return -1;
	while (ch[now][0])
		now = ch[now][0];
	return now;
}
int main(){
	int n;
	while (~scanf("%d", &n)){
		root = len = 0;
		int ans = 0;
		int v;
		while (n--){
			scanf("%d", &v);
			if (len){
				if (insert(v)){
					int pre = getpre(root);
					int next = getnext(root);
					int temp = inf;
					if (~pre)
						temp = min(temp, v-value[pre]);
					if (~next)
						temp = min(temp, value[next]-v);
					ans += temp;
				}
			}
			else{
				ans += v;
				newnode(root, 0, v);
			}
		}
		printf("%d\n", ans);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值