Acwing.提高课.营业额统计(c++题解)

Tiger 最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。

Tiger 拿出了公司的账本,账本上记录了公司成立以来每天的营业额。

分析营业情况是一项相当复杂的工作。

由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。

经济管理学上定义了一种最小波动值来衡量这种情况。

设第 i 天的营业额为 ai,则第 i 天(i≥2)的最小波动值 fi 被定义为:

fi=min1≤j<i|ai−aj|

当最小波动值越大时,就说明营业情况越不稳定。

而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。

你的任务就是编写一个程序帮助 Tiger 来计算这一个值。

第一天的最小波动值为第一天的营业额 a1。

输入格式

第一行为正整数 n,表示该公司从成立一直到现在的天数。

接下来的 n 行每行有一个整数 ai(有可能有负数) ,表示第 i 天公司的营业额。

输出格式

输出一个正整数,表示最小波动值的和。

数据范围

1≤n≤32767,|ai|≤10^6

输入样例:
6
5
1
2
5
4
6
输出样例:
12
样例解释

在样例中,5+|1−5|+|2−1|+|5−5|+|4−5|+|6−5|=5+4+1+0+1+1=12

_____________________________________________________________________________

写作不易,点个赞呗!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 

_____________________________________________________________________________

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5,inf=1e8;
struct node{
	int l,r;
	int key,val;//val用于决定这颗树的形态 
	int cnt,size;//cnt表示这个数出现多少次 
}tr[N];
int idx,root;
int n;
int ans;
int push_up(int u){
	tr[u].size=tr[tr[u].l].size+tr[tr[u].r].size+tr[u].cnt;
}
int get_node(int key){
	tr[++idx].key=key;
	tr[idx].val=rand();//随机函数 
	tr[idx].cnt=tr[idx].size=1;
	return idx; 
} 
void zag(int &p){//左旋,p指向根节点,因为根节点会变化 
	int q=tr[p].r;
	tr[p].r=tr[q].l,tr[q].l=p,p=q;
	push_up(tr[p].l),push_up(p);
}
void zig(int &p){//右旋,p指向根节点,因为根节点会变化 
	int q=tr[p].l;
	tr[p].l=tr[q].r,tr[q].r=p,p=q;
	push_up(tr[p].r),push_up(p);
}
void build(){//初始化2个哨兵 
	get_node(-inf),get_node(inf);
	root=1,tr[1].r=2;
	push_up(root);
	if(tr[1].val<tr[2].val)zag(root);
}
void insert(int &p,int key){
	if(!p)p=get_node(key);//判断树是否为空 
	else if(tr[p].key==key)tr[p].cnt++; 
	else if(tr[p].key>key){
		insert(tr[p].l,key);
		if(tr[tr[p].l].val>tr[p].val)zig(p);
	}else{
		insert(tr[p].r,key);
		if(tr[tr[p].r].val>tr[p].val)zag(p);
	}
	push_up(p);
}
void remove(int &p,int key){
	if(!p)return ;//判断树是否为空
	if(tr[p].key==key){
		if(tr[p].cnt>1)tr[p].cnt--;
		else if(tr[p].l||tr[p].r){//不是叶子节点 
			if(!tr[p].r||tr[tr[p].l].val>tr[tr[p].r].val){//通过左右旋将该节点移动向叶节点 
				zig(p);
				remove(tr[p].r,key);
			}else{
			    zag(p);
			    remove(tr[p].l,key);	
			}
		}else p=0;//是叶子节点 
	}else if(tr[p].key>key)remove(tr[p].l,key);
	else remove(tr[p].r,key);
	push_up(p);
} 
int get_rank_by_key(int p,int key){
	if(!p)return 0;//特殊情况
	if(tr[p].key==key)return tr[tr[p].l].size+1;
	if(tr[p].key>key)return get_rank_by_key(tr[p].l,key);
	return tr[tr[p].l].size+tr[p].cnt+get_rank_by_key(tr[p].r,key);
}
int get_key_by_rank(int p,int rank){
	if(!p)return inf;//特殊情况
	if(tr[tr[p].l].size>=rank)return get_key_by_rank(tr[p].l,rank);
	if(tr[tr[p].l].size+tr[p].cnt>=rank)return tr[p].key;
	return get_key_by_rank(tr[p].r,rank-tr[tr[p].l].size-tr[p].cnt);
}
int get_prev(int p,int key){
	if(!p)return -inf;//特殊情况
	if(tr[p].key>key)return get_prev(tr[p].l,key);
	return max(tr[p].key,get_prev(tr[p].r,key));
}
int get_next(int p,int key){
	if(!p)return inf;//特殊情况
	if(tr[p].key<key)return get_next(tr[p].r,key);
	return min(tr[p].key,get_next(tr[p].l,key));
}
signed main(){
	build();
	cin>>n;
	int v;
	cin>>v;insert(root,v);
	ans+=v;
	for(int i=2;i<=n;i++){
		cin>>v;
		int x=abs(v-get_prev(root,v));
		int y=abs(v-get_next(root,v));
		ans+=min(x,y);
		insert(root,v);
	}
	cout<<ans;
}

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值