BZOJ 1588 HNOI2002 营业额统计 Treap

题目大意:统计营业额。每天的统计的数字是今天的营业额和以前所有的营业额的最小差值。


思路:任何平衡树都可以。


CODE:


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define INF 10000000
using namespace std;

struct Complex{
	int random,val,cnt,size;
	Complex *son[2];

	Complex() {
		random = rand();
		cnt = size = 1;
		son[0] = son[1] = NULL; 
	}
	void Maintain() {
		size = cnt;
		if(son[0] != NULL)	size += son[0]->size;
		if(son[1] != NULL)	size += son[1]->size;
	}
	int Compare(int x) {
		if(x == val)	return -1;
		return x > val;
	}
}*root;

int cnt;

inline void Rotate(Complex *&a,bool dir);
void Insert(Complex *&a,int x);
int FindPred(Complex *a,int x);
int FindSucc(Complex *a,int x);

int main()
{
	int ans = 0;
	cin >> cnt;
	for(int x,i = 1;i <= cnt; ++i) {
		if(scanf("%d",&x) == EOF)	x = 0;
		int pred = FindPred(root,x);
		int succ = FindSucc(root,x);
		Insert(root,x);
		if(i == 1)	ans = x;
		else	ans += min(x - pred,succ - x);
	}
	cout << ans << endl;
	return 0;
}

inline void Rotate(Complex *&a,bool dir)
{
	Complex *k = a->son[!dir];
	a->son[!dir] = k->son[dir];
	k->son[dir] = a;
	a->Maintain(),k->Maintain();
	a = k;
}

void Insert(Complex *&a,int x)
{
	if(a == NULL) {
		a = new Complex();
		a->val = x;
		return ;
	}
	int dir = a->Compare(x);
	if(dir == -1)
		a->cnt++;
	else {
		Insert(a->son[dir],x);
		if(a->son[dir]->random > a->random)
			Rotate(a,!dir);
	}
	a->Maintain();
}

int FindPred(Complex *a,int x)
{
	if(a == NULL)	return -INF;
	if(a->val > x)	return FindPred(a->son[0],x);
	return max(a->val,FindPred(a->son[1],x));
}

int FindSucc(Complex *a,int x)
{
	if(a == NULL)	return INF;
	if(a->val < x)	return FindSucc(a->son[1],x);
	return min(a->val,FindSucc(a->son[0],x));
}


你可能感兴趣的:(treap,splay,平衡树,bzoj,BZOJ1588)