hnoi2002 bzoj1588 营业额统计【splay】【有坑。。】

大水题啊

很多种方法  

对于开始学splay的我  

就当一个练手题了。。。


特别吐槽

bzoj数据不对


有些数据说好的n行

却读入不够n行


加上   

if(scanf("%d",&t) == EOF) t = 0;

才能A


害我白错几次

幸好用小号、。。。。


#include <cstdio>
#include <iostream>

#define D 100000
#define lp(i,j,k) for(int i = j;i <= k;++i)

using namespace std;

int abs (int X) {
	if(X > 0)
		return X;
	return -X;
}

int n,t,a;

int ch[D][2],root = 1,x[D],fa[D],cnt,tim[D];

int point (int X,int now) {
	int d;
	if(x[now] > X)
		d = 0;
	else {
		if(x[now] < X) {
			d = 1;
		}
		else return -1;
	}
	return d;
}

void rot (int now,int d) {
	int temp = fa[now];
	
	ch[ fa[now] ][d ^ 1] = ch[now][d];
	fa[ch[now][d]] = fa[now];
	ch[now][d] = fa[now];
	
	fa[now] = fa[fa[now]];
	fa[temp] = now;
	
	if(!fa[now])
		return;
		
	if(ch[fa[now]][1] == temp)
		ch[fa[now]][1] = now;
	else ch[fa[now]][0] = now;
}
void splay (int X,int &goal) {
	if(X == goal)
		return;
	while(fa[X] != 0) {		
		if(fa[fa[X]]) {
			int T = 0;	
			lp(i,0,1) {
				lp(j,0,1) {
					if(ch[ fa[fa[X]] ][i] == fa[X] && ch[ fa[X] ][j] == X ) {
						rot(X,j ^ 1);
						rot(X,i ^ 1);
						T = 1;
						break;
					}					
				}
				if(T) break;
			}
		}
		else rot(X, ch[goal][1] == X ? 0 : 1 );
	}
	goal = X;
}
void insert (int X,int now) {
	if(cnt == 0) {
		x[now] = X;
		++cnt;
		++tim[now];
		return;
	}
	int d = point(X,now);
	if(d == -1) {
		++tim[now];
		splay(now,root);
		return;
	}
	if(!ch[now][d]) {
		ch[now][d] = ++cnt;
		fa[cnt] = now;
		x[cnt] = X;
		++tim[cnt];
 		splay(cnt,root);
		return;
	}
	else insert(X,ch[now][d]);
}


int search (int d) {				//前驱 1 后继 0
	if(tim[root] >= 2)
		return x[root];
	int p = ch[root][d ^ 1];
	if(!p)
		return 0x3f3f3f3f;
	while(ch[p][d])
		p = ch[p][d];
	return x[p];
}

void solve () {
	lp(i,1,n) {
		if(scanf("%d",&t) == EOF) t = 0;
		
		insert(t,root);	
		if(i == 1) {
			a += x[root];
			continue;
		}
		int t1 = abs(search(1) - t);
		int t2 = abs(search(0) - t);
			
		a += min(t1,t2);
	}
	printf("%d\n",a);
}

int main () {
	scanf("%d",&n);
	solve();
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值