P3369 【模板】普通平衡树 0pts 玄关求调
  • 板块灌水区
  • 楼主M_Jun
  • 当前回复31
  • 已保存回复31
  • 发布时间2025/2/6 10:31
  • 上次更新2025/2/6 13:47:20
查看原帖
P3369 【模板】普通平衡树 0pts 玄关求调
1098953
M_Jun楼主2025/2/6 10:31

rt,link

AI 用不了,只有求助万能的谷友了

代码如下:

#include <iostream>
#include <cstdio>
#include <vector>

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

using namespace std ;

typedef long long lint ;
typedef long double dint ;
struct SplayTree {
	
	struct Tree {
		lint cnt ;
		lint val ;
		lint Size ;
		lint son[2] ;
		lint father ;
		void init() {
			cnt = val = 0 ;
			Size = father = 0 ;
			son[0] = son[1] = 0 ;
		}
	};
	
	vector<Tree> tree ;
	lint cnt, now, root ;
	void init() {
		tree.resize(int(1e5 + 5)) ;
		for (int i = 1 ; i <= int(1e5 + 5) ; i ++) 
			tree[i].init() ;
	}
	
	// 更新:向上更新父节点的子树大小
	void push_up(lint x) {
		tree[x].Size += tree[x].cnt ;
		tree[x].Size += tree[tree[x].son[0]].Size ;
		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) ; // 父节点是爷节点的 左/右 儿子
		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] = fa ; // 旋转到父节点之上(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 ;
	}
	
	// 插入:在平衡树中以 root 为根节点、val 为权值、fa 为父节点,插入一个节点
	void insert(lint Root, lint val, lint fa) {
		if (!Root) {
			cnt ++ ;
			tree[cnt].val = val ; // 传参:权值
			tree[cnt].father = fa ; // 传参:父节点
			tree[cnt].Size = tree[cnt].cnt = 1 ; // 初始化
			if (val < tree[fa].val) tree[fa].son[0] = cnt ;
			else tree[fa].son[1] = cnt ; // 判断插入的节点 x 与父节点 fa 的关系
			if (cnt == 1) root = cnt ;
			now = cnt ;
			return ;
		}
	}
	
	// 查找(1):查找第 x 小的元素
	lint find_num(lint x) {
		lint sum = 0 ;
		lint Root = root ;
		while (Root) {
			if (tree[tree[Root].son[0]].Size + tree[Root].cnt >= x) { // 目标元素在当前节点或左子树中 
				if (tree[tree[Root].son[0]].Size < x) return Root ; // 目标元素是当前节点或其右子树的某个元素
				else sum = Root, Root = tree[Root].son[1] ; // 继续在左子树中找
			} else { // 目标元素在右子树中
				x -= tree[tree[Root].son[0]].Size + tree[Root].cnt ; // 更新 x
				sum = Root, Root = tree[Root].son[1] ; // 继续在左子树中找
			}
		}
		return sum ;
	}
	
	// 查找(2):查找一个给定值 x 的排名
	lint find_rank(lint val) {
		lint Root = root ;
		lint sum = 0, fa = 0 ;
		while (Root) {
			if (tree[Root].val < val) { // 当前节点及其左子树中的元素数目都小于 val
				sum += tree[tree[Root].son[0]].Size = tree[Root].cnt ;
				fa = Root, Root = tree[Root].son[1] ; // 进入右子树继续查找
			} else {
				fa = Root, Root = tree[Root].son[0] ; // 进入左子树继续查找
			}
		}
		Splay(fa, 0) ;
		return sum ;
	}
	
	// 查找(3):查找给定数 x 的前驱
	lint find_Predecessor(lint x) {
		lint Root = root, sum = 0 ;
		while (Root) {
			if (tree[Root].val >= x) // 当前节点值大于等于 x,前驱在左子树中
				Root = tree[Root].son[0] ;
			else sum = Root, Root = tree[Root].son[1] ; // 更新 sum,继续在右子树中查找
		}
		return sum ;
	}
	
	// 查找(4):查找给定数 x 的后继
	lint find_Successor(lint x) {
		lint sum = 0 ;
		lint Root = root ;
		while (Root) {
			if (tree[Root].val < x) // 当前节点值小于 x,后继在右子树中
				Root = tree[Root].son[1] ;
			else sum = Root, Root = tree[Root].son[0] ; // 更新 sum,继续在左子树中查找
		}
		return sum ;
	}
	
	// 删除:删除一个值为 x 的节点
	void Delete(lint x) {
		lint Subsequent = find_Successor(x) ;
		lint Precursor = find_Predecessor(x) ;
		Splay(Precursor, 0), Splay(Subsequent, root) ;
		lint rs = tree[root].son[1] ; // 根的右子树
		lint rsls = tree[rs].son[0] ; // rs 的左子树
		if (tree[rsls].cnt > 1) 
			tree[rsls].cnt --, tree[rsls].Size -- ;
		else 
			tree[rs].son[0] = 0, tree[rsls].cnt --, tree[rsls].Size -- ;
		push_up(rs), push_up(rs) ; // 更新节点大小
	}
};

lint n ;
lint opt, x ;

SplayTree splaytree ;

signed main () {
	
	cin >> n ;
	for (lint i = 1 ; i <= n ; i ++) {
		cin >> opt >> x ;
		if (opt == 1) splaytree.insert(1, x, 1) ;
		else if (opt == 2) splaytree.Delete(x) ;
		else if (opt == 3) cout << splaytree.cnt - splaytree.find_rank(x) + 1 << '\n' ;
		else if (opt == 4) cout << splaytree.find_num(x) << '\n' ;
		else if (opt == 5) cout << splaytree.find_Predecessor(x) << '\n' ;
		else if (opt == 6) cout << splaytree.find_Successor(x) << '\n' ;
	}
	
	return 0 ;
}
2025/2/6 10:31
加载中...