Treap的模板题65pts,求调
查看原帖
Treap的模板题65pts,求调
1039923
_Accepted_100楼主2024/8/9 10:11

Treap的模板题65pts, 错 #8 ~ #12测试点点

有没有哪位大佬和我错了同样的测试点的,求调

在线等, 急

#include <bits/stdc++.h>
using namespace std;

const int INF = 0x7fffffff;
const int N = 100010;
int n, root, tot;
struct Treap {
	int l, r;
	int val, dat; 
	int cnt, size;
} t[N];

void cprintf(int p) {
	cout << p << " " << t[p].cnt << " " << t[p].size << " " << t[p].val << endl;
}

int New(int val) {
	t[++tot].val = val;
	t[tot].dat = rand();
	t[tot].cnt = t[tot].size = 1;
	return tot;
}

void update(int p) {
	t[p].size = t[t[p].l].size + t[t[p].r].size + t[p].cnt;
}

void build() {
	New(-INF), New(INF);
	root = 1, t[1].r = 2;
	update(root);
	update(t[root].r);
}

void turn_left(int &p) {
	int q = t[p].r;
	t[p].r = t[q].l;
	t[q].l = p;
	p = q;
	update(t[p].l);
	update(p);
}

void turn_right(int &p) {
	int q =  t[p].l;
	t[p].l = t[q].r;
	t[q].r = p;
	p = q;
	update(t[p].r);
	update(p);
}

void insert(int &p, int val) {
	if (p == 0) {             																		//到一个空节点 
		p = New(val);																				//建立一个新节点 																				
		return;
	} if (t[p].val == val) {																		//重复,cnt++即可 
		t[p].cnt++;
		update(p);																					//cnt更新,size也要更新 
		return;
	} if (val < t[p].val) {																			//往左子树
		insert(t[p].l, val);								 
		if (t[t[p].l].dat > t[p].dat) turn_right(p); 												//维护堆性质 
	} else {																						//右子树同理 
		insert(t[p].r, val);
		if (t[t[p].r].dat > t[p].dat) turn_left(p); 
	}
	update(p);																						//递归向上更新 
}

void remove(int &p, int val) {	
//	cprintf(p);		
	if (p == 0) return;																				//没有val 
	if (t[p].val == val) {
		if (t[p].cnt > 1) {																			//重复,cnt--即可 
			t[p].cnt--;
			update(p);																				//cnt更新,size也要更新 
			return;
		} if (t[p].l != 0 or t[p].r != 0) {
			if (t[p].r == 0 or t[t[p].l].dat > t[t[p].r].dat) turn_right(p), remove(t[p].r, val);	//维护堆性质 
			else turn_left(p), remove(t[p].l, val);
			update(p);																				//改变树结构,更新 		
		} else p = 0; 																				//叶子结点,直接删除
		return;
	}
	val < t[p].val ? remove(t[p].l, val) : remove(t[p].r, val);										//找 
	update(p);																						//自底向上更新 
//	cprintf(p);																					
}

int grbv(int p, int val) {
	if (p == 0) return 1;
	if (val == t[p].val) return t[t[p].l].size + 1;													//找到,返回左子树的个数+1 
	if (val < t[p].val) return grbv(t[p].l, val);													//val在左子树, 递归 
	return t[t[p].l].size + t[p].cnt + grbv(t[p].r, val); 											//val在右子树,返回左子树的个数+p的副本数量+右子树递归 
}

int gvbr(int p, int rank) {
	if (p == 0) {
//		cout << t[root].size << " " << rank << endl;
		return INF;
	}
	if (t[t[p].l].size >= rank) return gvbr(t[p].l, rank);											//val被包含在左子树 
	if (t[t[p].l].size + t[p].cnt >= rank) return t[p].val;											//val是p的副本中的一个 
	return gvbr(t[p].r, rank - t[t[p].l].size - t[p].cnt);											//val在右子树, 只找排名为rank-t[t[p].l].size-t[p].cnt的val 
}

int get_pre(int val) {
	int ans = 1;
	int p = root;
	while (p != 0) {
		if (t[p].val == val) {   																	//找到 
			if (t[p].l > 0) {																		//非空	
				p = t[p].l;																			//赋值为左子树 
				while(t[p].r > 0) {  																//左子树一直向右找 
					p = t[p].r;
				}
				ans = p;																			//更新ans 
			}
			break;
		}
		if (val > t[p].val and t[p].val > t[ans].val)  ans = p;										//如果是右子树,它的前驱可能为当前的根节点 
		p = val < t[p].val ? t[p].l : t[p].r;  														//找val 
	}
	return t[ans].val;
}

int get_next(int val) {
	int ans = 2;
	int p = root;
	while (p != 0) {
		if (t[p].val == val) {    																	//找到 
			if (t[p].r > 0) {																		//非空
				int p = t[p].r;																		//赋值为右子树 
				while(t[p].l > 0) { 																//右子树一直向左找 
					p = t[p].l;
				}
				ans = p;																			//更新ans 
			}
			break;
		}
		if (val < t[p].val and t[p].val < t[ans].val)  ans = p;										//如果是左子树,它的后继可能为当前的根节点 
		p = val < t[p].val ? t[p].l : t[p].r;  														//找val 
	}
	return t[ans].val;
}

int main() {
	ios :: sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	build();
	while (n--) {
		int opt, x;
		cin >> opt >> x;
		switch (opt) {
			case 1:
				insert(root, x);
				break;
			case 2:
				remove(root, x);
				break;
			case 3:
				cout << grbv(root, x) - 1 << endl;
				break;
			case 4:
				cout << gvbr(root, x + 1) << endl;
				break;
			case 5:
				cout << get_pre(x) << endl;
				break;
			case 6:
				cout << get_next(x) << endl;
				break;
		}
//		cout << t[root].size << endl;
	}
	return 0;
}
2024/8/9 10:11
加载中...