P3369 【模板】普通平衡树 0pts 玄关求助
  • 板块学术版
  • 楼主M_Jun
  • 当前回复3
  • 已保存回复3
  • 发布时间2025/2/6 16:20
  • 上次更新2025/2/6 17:06:22
查看原帖
P3369 【模板】普通平衡树 0pts 玄关求助
1098953
M_Jun楼主2025/2/6 16:20

rt, link

源码:

#include <iostream>
#include <vector>

#define which(x) (tree[tree[x].father].son[0] == x)

using namespace std ;

typedef int lint ;

struct SplayTree {
	
	struct Tree {
		lint cnt ;
		lint val ;
		lint lazy ;
		lint Size ;
		lint son[2] ;
		lint father ;
		
		inline void init(lint _v, lint _fa) {
			cnt = Size = 1 ;
			val = _v ;
			father = _fa ;
			son[0] = son[1] = 0 ;
			lazy = false ;
		}
	} ;
	
	vector<Tree> tree ;
	lint cnt_tree, now, root ;
	
	// 初始化树
	void init() {
		tree.resize(lint(1e5 + 5), Tree()) ;
		cnt_tree = 0 ; // 初始化 cnt
		root = 0 ; // 初始化根节点为0
	}
	
	// 更新:从当前点 x 向上更新父节点的子树大小
	void push_up(lint x) {
		if (x == 0) return ; // 防止访问空节点
		tree[x].Size = tree[x].cnt ;
		if (tree[x].son[0]) tree[x].Size += tree[tree[x].son[0]].Size ;
		if (tree[x].son[1]) tree[x].Size += tree[tree[x].son[1]].Size ;
	}
	
	// 旋转(单旋)将 x 点旋转到父结点处
	void revolve(lint x) {
		lint fa = tree[x].father ; // 父节点
		lint gf = tree[fa].father ; // 爷节点
		bool whichfa = which(x) ; // 此节点是父节点的 左/右 儿子
		bool whichgf = which(fa) ; // 父节点是爷节点的 左/右 儿子
		if (tree[x].son[!whichfa]) tree[tree[x].son[!whichfa]].father = fa ; // 子节点过继(1)
		tree[fa].son[whichfa] = tree[x].son[!whichfa] ; // 子节点过继(2)
		tree[x].son[!whichfa] = fa ; // 旋转到父节点之上(1)改变父子关系
		tree[gf].son[whichgf] = x ; // 旋转到父节点之上(2)改变父子关系
		tree[fa].father = x ; // 旋转到父节点之上(3)改变爷孙关系
		tree[x].father = gf ; // 旋转到父节点之上(4)改变爷孙关系
		push_up(fa), push_up(x) ; // 旋转到父节点之上(5)子树大小更新
	}
	
	// 旋转(双旋):将 x 点旋转到目标点 y 的下方
	void Splay(lint x, lint y) {
		lint fa, gf ;
		if (x == y) return ;
		while (tree[x].father != y) {
			fa = tree[x].father ;
			gf = tree[fa].father ;
			if (gf != y) {
				if (which(fa) == which(x)) // x, fa, gf 三点共线
					revolve(fa) ; // 先旋转父节点
				else // x, fa, gf 三点呈之字形
					revolve(x) ; // 多旋转一次 x 节点
			}
			revolve(x) ;
		}
		if (!y)
			root = x ;
	}
	
	// 插入:在平衡树中以val 为权值插入一个节点
	void insert(lint val) {
		lint fa = 0 ;
		lint u = root ;
		while (u && tree[u].val != val) {
			fa = u ;
			if (val > tree[u].val) // 去右子树
				u = tree[u].son[1] ;
			else u = tree[u].son[0] ; // 去左子树
		}
		if (u) 
			tree[u].cnt ++ ;
		else {
			cnt_tree ++ ;
			u = cnt_tree ;
			if (fa) {
				if (val > tree[fa].val) // 去右子树
					tree[fa].son[1] = u ;
				else tree[fa].son[0] = u ; // 去左子树
			}
		}
		Splay (u, 0) ;
	}
	
	// 查找(1):查找到数 x 并将它上提到根
	void Find(lint x) {
		lint u = root ;
		if (!u) return ;
		if (x > tree[u].val) 
			while (tree[u].son[1] && x != tree[u].val)
				u = tree[u].son[1] ;
		if (x < tree[u].val) 
			while (tree[u].son[0] && x != tree[u].val)
				u = tree[u].son[0] ;
		Splay(u, 0) ;
		return ;
	}
	
	// 查找(2):查找一个给定值 x 的排名
	lint Rank(lint val) {
		Find(val) ;
		return tree[tree[root].son[0]].Size ;
	}
	
	// 查找(3):查找第 x 小的元素
	lint Search(lint x) {
		lint u = root ;
		if (tree[u].Size < x)
			return -1 ;
		while (true) {
			if (x > tree[tree[u].son[0]].Size + tree[u].cnt){
				x -= tree[tree[u].son[0]].Size + tree[u].cnt ;
				u = tree[u].son[1] ;
			} else {
				if (tree[tree[u].son[0]].Size >= x)
					u = tree[u].son[0] ;
				else return tree[u].val ;
			}
		}
	}
	
	// 查找(4):查找给定数 x 的前驱
	lint Predecessor(lint x) {
		Find(x) ;
		lint u = root ;
		if (tree[u].val >= x)
			return u ;
		u = tree[u].son[0] ;
		while (tree[u].son[1])
			u = tree[u].son[1] ;
		return u ;
	}
	
	// 查找(5):查找给定数 x 的后继
	lint Successor(lint x) {
		Find(x) ;
		lint u = root ;
		if (tree[u].val >= x)
			return u ;
		u = tree[u].son[1] ;
		while (tree[u].son[0])
			u = tree[u].son[0] ;
		return u ;
	}
	
	// 删除:删除一个值为 x 的节点
	void Delete(lint x) {
		lint l = Successor(x) ;
		lint r = Predecessor(x) ;
		Splay(r, 0), Splay(l, r) ;
		if (tree[tree[r].son[0]].cnt > 1) {
			tree[tree[r].son[0]].cnt -- ;
			Splay(tree[r].son[0], 0) ;
		} else tree[r].son[0] = 0 ;
	}
} ;

lint n ;
lint opt, x ;

SplayTree splaytree ;

inline void read(lint &x) {
	char c ; bool b = true ;
	for (c = getchar() ; !isdigit(c) ; c = getchar())
		if (c == '-') b = !b ;
	for (x = 0 ; isdigit(c) ; c = getchar())
		x = x * 10 + c - '0' ;
	if (b == false)
		x *= -1 ;
	return ;
}

signed main() {
	read(n) ;
	splaytree.init() ; // 初始化树
	for (lint i = 1 ; i <= n ; i ++) {
		read(opt), read(x) ;
		if (opt == 1) splaytree.insert(x) ;
		else if (opt == 2) splaytree.Delete(x) ;
		else if (opt == 3) cout << splaytree.Rank(x) << '\n' ;
		else if (opt == 4) cout << splaytree.Search(x) << '\n' ;
		else if (opt == 5) cout << splaytree.Predecessor(x) << '\n' ;
		else if (opt == 6) cout << splaytree.Successor(x) << '\n' ;
	}
	return 0 ;
}

@Statax @DX3906_ourstar @StarryRTX @jerry1717 %%%

2025/2/6 16:20
加载中...