首页 > 其他分享 >平衡树

平衡树

时间:2023-03-29 20:12:31浏览次数:22  
标签:rt ch return val int 平衡 now

简单写一下 splay。

刚刚写了一下没写出除了少 splay 以外的任何锅来。令人感慨。

所有操作都是基于朴素二叉搜索树,只是加入了一个 splay 操作均摊复杂度。

\(splay(u,x)\) 表示把 \(u\) 旋转到 \(x\) 的儿子位置(如果 \(x=0\) 则转到根)。

旋转采用双旋保证复杂度。对于一个点 \(x\) 和他的父亲 \(y\) 和 \(y\) 的父亲 \(z\),如果三者在树上的儿子关系相同,那么先转 \(y\) 再转 \(x\),否则转两次 \(x\)。

旋转的方式手玩一下就能玩出来,保证二叉搜索树的性质即可。

然后注意不管干什么操作,如果找到了某个点,都要在最后 \(splay\) 这个点到根以保证复杂度。

code:

#include<bits/stdc++.h>
//#include <ext/pb_ds/hash_policy.hpp>
//#include <ext/pb_ds/assoc_container.hpp>
namespace infinities{
	#define fint register int
	#define ls(i) (i << 1)
	#define rs(i) ((i << 1) | 1)
	#define pii pair<int, int>
	#define im int mid = (l + r) >> 1
	#define INT __int128
	#define ll long long
	#define ui unsigned int
	#define ull unsigned long long
	#define lc ch[now][0]
	#define rc ch[now][1]
	const int mod = 998244353, INF = 1e9 + 6e8 + 7, maxn = 2e6 + 2e5 + 7;
	namespace FastIO{//10M
		const int SS = 1e7; char num_[50]; int cnt_;
		inline int xchar(){static char buf[SS]; static int len = 0, pos = 0; if(pos == len)pos = 0, len = fread(buf, 1, SS, stdin); if(pos == len)exit(0); return buf[pos++];}
		inline int read(){fint x = 0, f = 1, ch = getchar(); while(ch < '0' || ch > '9'){if(ch == '-')f = -1; ch = getchar();}while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();} return x * f;}
		inline void write(int x){if(x == 0){putchar('0'); return;}if(x < 0)putchar('-'), x = -x; while(x)num_[++cnt_] = x % 10 ^ 48,x /= 10; while(cnt_)putchar(num_[cnt_--]);}
		inline void write(int x, char c){write(x), putchar(c);}
	}
	//using namespace __gnu_pbds;
	//gp_hash_table<int, int>hsh;
	void file(){freopen("P6136_5.in", "r", stdin);}
	using namespace std;
	using namespace FastIO;
	namespace mystd{
		inline void chkmin(int &a, int b){a = min(a, b); return;} inline void chkmax(int &a, int b){a = max(a, b); return;}
		inline void qk(int &a, int b){a = a + b; a = (a >= mod) ? a - mod : a;}
		inline void sub(int &a, int b){a = a - b + mod; a = (a >= mod) ? a - mod : a;}
		inline int qpow(int x, int k){fint res = 1; for(; k; k = (k >> 1), x = 1ll * x * x % mod)if(k & 1)res = 1ll * res * x % mod; return res;}
	}
	using namespace mystd;
	int n, ch[maxn][2], size[maxn], cnt[maxn], fa[maxn], rt, val[maxn], tot;
	int newnode(){++tot; size[tot] = ch[tot][0] = ch[tot][1] = fa[tot] = cnt[tot] = val[tot] = 0; return tot;}
	void pu(int now){size[now] = size[ch[now][0]] + size[ch[now][1]] + cnt[now];}
	void rotate(int x){
		fint y = fa[x], z = fa[y];
		bool fl = (ch[y][1] == x);
		ch[y][fl] = ch[x][fl ^ 1];
		ch[x][fl ^ 1] = y, fa[ch[y][fl]] = y, fa[ch[x][fl ^ 1]] = x;
		fa[x] = z, ch[z][ch[z][1] == y] = x;
		pu(y), pu(x);
	}
	void splay(int x, int v){
		while(fa[x] != v){
			fint y = fa[x], z = fa[y];
			if(z == v){rotate(x); break;}
			((ch[z][1] == y) == (ch[y][1] == x)) ? rotate(y) : rotate(x);
			rotate(x);
		}
		if(v == 0)rt = x;
	}
	bool find(int x){
		if(!rt)return 0;
		fint now = rt;
		while(val[now] != x && ch[now][x > val[now]])now = ch[now][x > val[now]];
		splay(now, 0);
		if(val[now] == x)return 1; return 0;
	}
	void insert(int x){
		if(!rt){rt = newnode(); cnt[rt] = size[rt] = 1, val[rt] = x; return;}
		if(find(x)){++cnt[rt]; pu(rt); return;}
		fint now = rt;
		while(ch[now][x > val[now]])now = ch[now][x > val[now]];
		ch[now][x > val[now]] = newnode();
		fa[tot] = now, val[tot] = x, cnt[tot] = 1, size[tot] = 1;
		splay(tot, 0);
	}
	int next(int x, int op){
		find(x);
		if(val[rt] < x && op == 0)return rt;
		if(val[rt] > x && op == 1)return rt;
		fint now = ch[rt][op];
		while(ch[now][op ^ 1])now = ch[now][op ^ 1];
		splay(now, 0);
		return now;
	}
	void del(int x){
		find(x);
		if(val[rt] != x)return;
		fint pre = next(x, 0), nxt = next(x, 1);
		splay(pre, 0), splay(nxt, pre);
		fint now = ch[nxt][0];
		if(now == 0)return;
		if(cnt[now] > 1){--cnt[now]; splay(now, 0); return;}
		fa[now] = ch[nxt][0] = 0;
		splay(nxt, 0);
	}
	int kth(int k){
		++k;
		fint now = rt;
		if(size[rt] < k)return val[next(INF, 0)];
		while(1){
			if(size[ch[now][0]] >= k){
				now = ch[now][0];
			}else
			if(size[ch[now][0]] + cnt[now] < k){
				k -= size[ch[now][0]] + cnt[now];
				now = ch[now][1];
			}else{splay(now, 0); return val[now];}
		}
	}
	int rk(int x){
		find(x);
		return size[ch[rt][0]] + ((val[rt] < x) ? cnt[rt] : 0);
	}
	int m, las = 0, all, a[maxn];
	signed main(){
		n = read(), m = read();
		insert(-INF), insert(INF);
		for(fint i = 1; i <= n; i++)a[i] = read();
		random_shuffle(a + 1, a + 1 + n);
		for(fint i = 1; i <= n; i++)insert(a[i]);
		while(m--){
			fint opt = read(), x = read() ^ las;
			if(opt == 1){insert(x);}
			if(opt == 2){del(x);}
			if(opt == 3){(las = rk(x));}
			if(opt == 4){(las = kth(x));}
			if(opt == 5){(las = val[next(x, 0)]);}
			if(opt == 6){(las = val[next(x, 1)]);}
			if(opt > 2){all ^= las;}
		}
		cout << all;
		return 0;
	}
}
signed main(){
    return infinities::main();
}

标签:rt,ch,return,val,int,平衡,now
From: https://www.cnblogs.com/infinities/p/17270171.html

相关文章

  • 平衡二叉树 -(avltree)
    AVL树简介AVL树的名字来源于发明作者G.M.Adelson-Velsky和E.M. Landis的缩写。AVL树是最先发明的自平衡二叉查找树(Self-BalancingBinarySearchTree,简称平衡二叉树......
  • 2023-03-25 AVL平衡树
    AVL平衡树1什么是AVL平衡树AVL是两个人的人名Adelson-Velsky和Landis,两个人都是俄罗斯人,是两人在1962年的论文中首次提出,是最早的自平衡二分搜索树什么是平衡二叉树......
  • SAP ABAP BAPI_ACC_DOCUMENT_POST创建会计凭证常见错误:1.借贷不平衡;2.FI/CO接口:多次
      解决办法:1.多次行项目检查是否指定itemno_acc行项目,如果指定了,要检查每个行项目是否+12.借贷不平衡检查是否传入记账码,如果记账码正确,检查金额是否为一正一负......
  • DolphinDB 数据迁移与再平衡
    数据迁移再平衡的目标是保证分区副本尽可能均衡分布,副本位置影响着IO性能、节点负载,对于数据访问延迟有着较大的影响。近来,越来越多的客户对于数据容量或计算性能提出了更......
  • 1541. 平衡括号字符串的最少插入次数
    给你一个括号字符串 s ,它只包含字符 '('和 ')' 。一个括号字符串被称为平衡的当它满足:任何左括号 '(' 必须对应两个连续的右括号 '))' 。左括号 '(' 必须在......
  • 「学习笔记」平衡树基础:Splay 和 Treap
    「学习笔记」平衡树基础:Splay和Treap点击查看目录目录「学习笔记」平衡树基础:Splay和Treap知识点平衡树概述Splay旋转操作Splay操作插入\(x\)查询排名为\(k\)......
  • 力扣---1664. 生成平衡数组的方案数
    给你一个整数数组nums。你需要选择恰好一个下标(下标从0开始)并删除对应的元素。请注意剩下元素的下标可能会因为删除操作而发生改变。比方说,如果nums=[6,1,7,4,1]......
  • Kafka Rebalance-重平衡
    消费者组ConsumerGroupKafka提供的可扩展且具有容错性的消费者机制共享一个公共的ID,这个ID被称为GroupID。组内的所有消费者协调在一起来消费订阅主题(Subscribe......
  • Windows server服务器之NLB网络负载平衡【转】
    占坑Windowsserver2012服务器之NLB网络负载平衡_张晓C的技术博客_51CTO博客https://blog.51cto.com/zhangcong/1658450(44条消息)windows——网络负载平衡(NLB)_window......
  • 算法学习笔记(18): 平衡树(一)
    平衡树建议在清楚二叉搜索树的所有操作之后食用本文。本文将略过部分基础知识目录平衡树Treap旋转插入删除其他操作FHQ-Treap分裂合并其他操作Splay旋转伸展其他操作WB......