HDU 4585 ShaoLin 基础Treap

这题其实就是一个在二叉搜索树里面找前驱和后继的题,以前好像用线段树+离散化搞过,弄得比较挫,学会AVL了之后就是方便。

简单说一下怎么找前驱和后继,

前驱的话,如果当前节点有左子树,那么前驱就是左子树中的最大节点,否则往上找第一个是他父亲节点的右儿子的节点,后继和前驱差不多,反过来就行。

因为我这里没有存parent指针,如果存的话旋转起来比较麻烦,所以我是先从根找到这个节点,沿途记录了一下。

#include <cstdio>
#include <climits>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <stack>

using namespace std;

typedef long long LL;

const int maxn = 2e5 + 10;

struct Node {
	Node *ch[2];
	int rkey, val, size, id;
	Node(int val, int id): val(val), id(id) {
		ch[0] = ch[1] = NULL;
		rkey = rand();
		size = 1;
	}
	void maintain() {
		size = 1;
		if(ch[1] != NULL) size += ch[1]->size;
		if(ch[0] != NULL) size += ch[0]->size;
	}
};

void rotate(Node *&o, int d) {
	Node *k = o->ch[d ^ 1];
	o->ch[d ^ 1] = k->ch[d];
	k->ch[d] = o;
	o->maintain(); k->maintain();
	o = k;
}

void insert(Node *&o, int x, int id) {
	if(o == NULL) o = new Node(x, id);
	else {
		int d = x > o->val;
		insert(o->ch[d], x, id);
		if(o->ch[d]->rkey > o->rkey) 
			rotate(o, d ^ 1);
	}
	o->maintain();
}

void remove_tree(Node *&o) {
	if(o == NULL) return;
	if(o->ch[0] != NULL) remove_tree(o->ch[0]);
	if(o->ch[1] != NULL) remove_tree(o->ch[1]);
	delete(o); o = NULL;
}

Node* query(Node *o, int x, int dx) {
	//dx = 0
	Node *pre = NULL;
	while(o != NULL && o->val != x) {
		int d = x > o->val;
		if(d == dx ^ 1) pre = o;
		o = o->ch[d];
	}
	o = o->ch[dx];
	if(o == NULL) return pre;
	else {
		while(o->ch[dx ^ 1] != NULL) 
			o = o->ch[dx ^ 1];
		return o;
	}
}

int calc(Node *r, int k) {
	if(r == NULL) return INT_MAX;
	return abs(r->val - k);
}

Node *root;
int n;

int main() {
	while(scanf("%d", &n), n != 0) {
		remove_tree(root);
		insert(root, 1e9, 1);
		for(int i = 1; i <= n; i++) {
			int id, k, ans; 
			scanf("%d%d", &id, &k);
			insert(root, k, id);
			Node *r0 = query(root, k, 0), 
				*r1 = query(root, k, 1);
			int d0 = calc(r0, k), d1 = calc(r1, k);
			if(d0 > d1) ans = r1->id;
			else ans = r0->id;
			printf("%d %d\n", id, ans);
		}
	}
	return 0;
}

  

posted @ 2015-02-06 11:15  acm_roll  阅读(500)  评论(0编辑  收藏  举报