您的位置:首页 > 其它

[BZOJ 1588][HNOI2002]营业额统计

2015-08-04 14:06 309 查看


1533. [HNOI2002]营业额统计

★★ 输入文件:
turnover.in
输出文件:
turnover.out
简单对比

时间限制:5 s 内存限制:162 MB


【题目描述】

Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。
Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:
该天的最小波动值=min{|该天以前某一天的营业额-该天营业额|}。

当最小波动值越大时,就说明营业情况越不稳定。
而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。
第一天的最小波动值为第一天的营业额。


【输入格式】

第一行为正整数n(n<=32767),表示该公司从成立一直到现在的天数,接下来的n行每行有一个正整数ai(ai<=1000000),表示第i天公司的营业额。


【输出格式】

输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。


【样例输入】

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


【来源】

HNOI 2002.

搞了半天的inf问题,难道真的是模板不好么。。喵。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 50000
#include<cmath>
using namespace std;
struct Tree{
	int l,r,val,key;
	#define l(x) tree[x].l
	#define r(x) tree[x].r
	#define val(x) tree[x].val
	#define key(x) tree[x].key
}tree[maxn];
int tot,n,root,ans,num;
const int inf=0x7fffffff;
int Newnode(int t){
	++tot;val(tot)=t;
	key(tot)=(rand()<<15|rand())&0x7fffffff;
	return tot;
}
int Zig(int x){//left up
	int y=l(x);l(x)=r(y);r(y)=x;
	return y;
}
int Zag(int x){//right up
	int y=r(x);r(x)=l(y);l(y)=x;
	return y;
}
int Insert(int x,int t){
	if(t<val(x))l(x)= !l(x)?Newnode(t):Insert(l(x),t);
	else r(x)= !r(x)?Newnode(t):Insert(r(x),t);
	if(key(x)>key(l(x)))x=Zig(x);
	else if(key(x)>key(r(x)))x=Zag(x);
	return x;
}
int Pre(int x){
	int now=root,ans=-10000000;
	while(now){
		if(val(now)<=x)ans=max(ans,val(now)),now=r(now);
		else now=l(now);
	}
	return ans;
}
int Suc(int x){
	int now=root,ans=10000000;
	while(now){
		if(val(now)>=x)ans=min(ans,val(now)),now=l(now);
		else now=r(now);
	}
	return ans;
}
void Init(){
	key(0)=inf;
	scanf("%d%d",&n,&num);
	ans=num;
	root=Newnode(-inf);
	root=Insert(root,inf);
	root=Insert(root,num);
} 
int Abs(int a){return a<0?-a:a;}
int main(){
	Init();
	for(int i=2;i<=n;i++){
		if(scanf("%d",&num)==EOF)num=0;
		ans+=min(Abs(num-Pre(num)),Abs(num-Suc(num)));
		root=Insert(root,num);
	}
	printf("%d",ans);
	return 0;
}


嗯,Splay的插入,旋转还有待练习

1.注意mark

2.注意新建节点时的边要连好

3.注意一字形,之字形,和只有两个的情况

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

#define maxn 50000
using namespace std;

int n,a[maxn];
struct Tree{
	int ch[2],val,fa;
	#define fa(x) tree[x].fa
	#define val(x) tree[x].val
	#define c(x,y) tree[x].ch[y]
}tree[maxn];
int ans,root,tot;
void Rotate(int &p,int &x){
	int mark= p==c(x,1),y=c(p,mark^1),z=fa(x);
	if(x==c(z,0))c(z,0)=p;
	if(x==c(z,1))c(z,1)=p;
	if(y)fa(y)=x;
	fa(p)=z;c(p,mark^1)=x;fa(x)=p;c(x,mark)=y;	
}
void Splay(int p){
	while(fa(p)){
		int x=fa(p),y=fa(x);
		if(y==0)Rotate(p,x);
		else if(p==c(x,0)^x==c(y,0))Rotate(p,x),Rotate(p,y);
		else Rotate(x,y),Rotate(p,x);
	}root=p;
}
void Insert(int t){
	int now=root,fa=root;
	while(now){
		fa=now;
		if(t<=val(now))now=c(now,0);
		else now=c(now,1);
	}++tot;val(tot)=t;fa(tot)=fa;
	if(fa)
		if(t<=val(fa))c(fa,0)=tot;
		else c(fa,1)=tot;
	Splay(tot);
}
int Pre(int k){
	int now=root,fa=root,ans=-0x7fffffff/3;
	while(now){
		fa=now;
		if(k<val(now))now=c(now,0);
		else ans=max(ans,val(now)),now=c(now,1);
	}Splay(fa);
	return ans;
}
int Suf(int k){
	int now=root,fa=root,ans=0x7fffffff/3;
	while(now){
		fa=now;
		if(k<=val(now))ans=min(ans,val(now)),now=c(now,0);
		else now=c(now,1);
	}Splay(fa);
	return ans;
}
int main(){
	scanf("%d",&n);
	scanf("%d",&ans);
	a[1]=ans;
	Insert(ans);
	for(int i=2;i<=n;i++){
		if(scanf("%d",&a[i])==EOF)a[i]=0;
		ans+=min(abs(a[i]-Pre(a[i])),abs(a[i]-Suf(a[i])));
		Insert(a[i]);
	}printf("%d",ans);
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: