首页 > 其他分享 >P3369 【模板】普通平衡树

P3369 【模板】普通平衡树

时间:2022-12-22 19:01:49浏览次数:63  
标签:get int void tr P3369 平衡 root 模板 size

题目链接

题目要求:插入数据,删除数据,查询数的排名,查询排名为x的 数,找前驱,找后继

  1. 旋转操作,左旋和右旋,旋转$x$,旋转操作一定要符合先序遍历前后一致
void rotate(int x){
	int y = tr[x].p, z = tr[y].p;
	int k = tr[y].s[1] == x;
	tr[z].s[tr[z].s[1] == y] = x;//更改z的儿子
	tr[tr[x].s[k ^ 1]].p = y;//因为x旋转后的一个儿子变成了y,所以x的有一个儿子要移动(相当于父亲改变)
	tr[y].s[k] = tr[x].s[k ^ 1];//移动的x的儿子就变成了y的儿子
	tr[x].s[k ^ 1] = y;
	tr[x].p = z, tr[y].p = x;
	pushup(y), pushup(x);
}
  1. 将x结点旋转到k结点下方,而且先序遍历前后一致
void splay(int x, int k){
	while(tr[x].p != k){
		int y = tr[x].p, z = tr[y].p;
		if(z != k)//观察其是折线形还是直线型
			(tr[y].s[0] == x) ^ (tr[z].s[0] == y)
				? rotate(x) : rotate(y);
		rotate(x);
	}
	if(k == 0) root = x;//是根节点还要更改根节点(root)的值
}
  1. 完整代码
#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 7;

struct node{
	int s[2], p, v, cnt, size;
	void init(int p1, int v1){
		p = p1, v = v1;
		cnt = size = 1;
	}
}tr[N];
int root, idx;

void pushup(int x){
	tr[x].size = tr[tr[x].s[0]].size + 
		tr[tr[x].s[1]].size + tr[x].cnt;
}

void rotate(int x){
	int y = tr[x].p, z = tr[y].p;
	int k = tr[y].s[1] == x;
	tr[z].s[tr[z].s[1] == y] = x;
	tr[tr[x].s[k ^ 1]].p = y;
	tr[y].s[k] = tr[x].s[k ^ 1];
	tr[x].s[k ^ 1] = y;
	tr[x].p = z, tr[y].p = x;
	pushup(y), pushup(x);
}

void splay(int x, int k){
	while(tr[x].p != k){
		int y = tr[x].p, z = tr[y].p;
		if(z != k)
			(tr[y].s[0] == x) ^ (tr[z].s[0] == y)
				? rotate(x) : rotate(y);
		rotate(x);
	}
	if(k == 0) root = x;
}

void find(int v){
	int x = root;
	while(tr[x].s[v > tr[x].v] && v != tr[x].v)
		x = tr[x].s[v > tr[x].v];
	splay(x, 0);
}

int get_pre(int v){
	find(v);
	int x = root;
	if(tr[x].v < v) return x;
	x = tr[x].s[0];
	while(tr[x].s[1]) x = tr[x].s[1];
	return x;
}

int get_suc(int v){
	find(v);
	int x = root;
	if(tr[x].v > v) return x;
	x = tr[x].s[1];
	while(tr[x].s[0]) x = tr[x].s[0];
	return x;
}

void del(int v){
	int pre = get_pre(v);
	int suc = get_suc(v);
	splay(pre, 0), splay(suc, pre);
	int del = tr[suc].s[0];
	if(tr[del].cnt > 1)
		tr[del].cnt --, splay(del, 0);
	else
		tr[suc].s[0] = 0, splay(suc, 0);
}

int get_rank(int v){
	find(v);
	return tr[tr[root].s[0]].size;
}

int get_val(int k){
	int x = root;
	while(1){
		int y = tr[x].s[0];
		if(tr[y].size + tr[x].cnt < k){
			k -= tr[y].size + tr[x].cnt;
			x = tr[x].s[1];
		}
		else{
			if(tr[y].size >= k) x = tr[x]. s[0];
			else break;
		}
	}
	splay(x, 0);
	return tr[x].v;
}

void insert(int v){
	int x = root, p = 0;
	while(x && tr[x].v != v)
		p = x, x = tr[x].s[v>tr[x].v];
	if(x) tr[x].cnt ++;
	else{
		x = ++ idx;
		tr[p].s[v > tr[p].v] = x;
		tr[x].init(p, v);
	}
	splay(x, 0);
}

int main(){
	int n, op, x;
	scanf("%d", &n);
	insert(-1e9), insert(1e9);
	while(n --){
		scanf("%d%d", &op, &x);
		if(op == 1) insert(x);
		else if(op == 2) del(x);
		else if(op == 3) printf("%d\n", get_rank(x));
		else if(op == 4) printf("%d\n", get_val(x + 1));
		else if(op == 5) printf("%d\n", tr[get_pre(x)].v);
		else printf("%d\n", tr[get_suc(x)].v);
	}
	return 0;
}

标签:get,int,void,tr,P3369,平衡,root,模板,size
From: https://www.cnblogs.com/loser--QAQ/p/16999399.html

相关文章

  • 哈啰出行高质量故障复盘法:“3+5+3”(附模板)
    #一分钟精华速览#故障复盘指的是及时把过去发生的错误,最大程度转化为未来可以规避的办法,其核心是不断减少失败因子繁衍的温床,将它们牢牢地掌控在不至于引发危机的范围之......
  • 条款43:学习处理模板化基类内的名称
    代码:#pragmaonce#include<iostream>#include<string>usingnamespacestd;classCompanyA{public:CompanyA(){}virtual~CompanyA()......
  • MyCms 自媒体系统 v4.2 ,全新后台模板发布
    MyCms是一款基于Laravel开发的开源免费的开源多语言商城CMS企业建站系统。MyCms基于Apache2.0开源协议发布,免费且可商业使用,欢迎持续关注我们。v4.2更新重点全......
  • Zabbix-4.zabbix的模板设置
    1.自定义监控内容#自定义监控服务器登陆的人数需求:限制登陆人数不超过三个,超过三个就发出报警信息 #先从命令行角度#明确需要执行的linux命令w......
  • nginx四层负载均衡配置模板
    一、模板1、nginx模板usernginxnginx;#cpu核数上百,设置成auto最方便worker_processesauto;worker_cpu_affinityauto;error_loglogs/error.log;worker_rlimit_nofile......
  • nginx高并发优化之模板
    下面的Nginx.conf实现nginx在前端做反向代理服务器的完整配置文件的例子,处理js、png等静态文件,jsp/php等动态请求转发到其它服务器tomcat/apacheuserwwwwww;worker_proce......
  • EBS:BI Publisher模板文件查询
    BIPublisher模板文件查询 --N:OracleXMLPublisher>>主页>>模板SELECTXT.TEMPLATE_ID,XT.TEMPLATE_NAMEAS"模板-名称",XT.TEMPLATE_CODEAS"......
  • P3372 【模板】线段树 1
    P3372【模板】线段树1题目简述对于一段数列,有如下两种操作1xyk:将区间\([x,y]\)内每个数加上\(k\)。2xy:输出区间\([x,y]\)内每个数的和。思路线段树......
  • 模板系列---数据结构
    P3378【模板】堆题目简述给定三个操作,求数列中最小的数,删除数列中最小的数,插入一个新的数思路板子题没什么好说,用stl自带的优先队列很好写,但手写的也要掌握。建议......
  • 免费表单模板库推荐
    相信大家在工作中或多或少都会遇到免费文档模板的难题,今天给大家带来一个好消息, ONLYOFFICE 一个专注于办公的软件,它几乎解决了所有在办公时遇到免费文档模板的难题,接下来......