P3369 【模板】普通平衡树

题目通道(【模板】普通平衡树 - 洛谷)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7;
#define int long long

struct node
{
	int l;
	int r;
	int val;
	int sval;
	int size;
};
node tree[maxn];
int root=0;
int idx=0;

void newnode(int &x,int v)
{
	x=++idx;
	tree[idx].val=v;
	tree[idx].sval=rand();
	tree[idx].size=1;
}

void pushup(int pos)
{
	tree[pos].size=tree[tree[pos].l].size+tree[tree[pos].r].size+1;
}

void split(int pos,int val,int &x,int &y)//按值分裂,取决于树的路径长,O(log n)
{
	if(!pos)
	{
		x=y=0;
		return;
	}
	if(tree[pos].val<=val)
	{
		x=pos;
		split(tree[x].r,val,tree[x].r,y);
		pushup(x);
	}
	else
	{
		y=pos;
		split(tree[y].l,val,x,tree[y].l);
		pushup(y);
	}
}

int merge(int x,int y)//只需要考虑两棵树根节点的大小,因为它们内部都是有序的。返回值为新树的根节点,O(log n)
{
	if(!x||!y)return x+y;
	if(tree[x].sval<tree[y].sval)
	{
		tree[x].r=merge(tree[x].r,y);
		pushup(x);
		return x;
	}
	else
	{
		tree[y].l=merge(x,tree[y].l);
		pushup(y);
		return y;
	}
}

void ins(int v)
{
	int x,y,z;
	split(root,v,x,y);
	newnode(z,v);
	root=merge(merge(x,z),y);
}

void del(int v)
{	
	int x,y,z;	
	split(root,v,x,z);
	split(x,v-1,x,y);
	y=merge(tree[y].l,tree[y].r);
	root=merge(merge(x,y),z);
}

int kth(int pos,int k)
{
	if(k==tree[tree[pos].l].size+1)
	{
		return tree[pos].val;
	}
	else if(k<=tree[tree[pos].l].size)
	{
		return kth(tree[pos].l,k);
	}
	else
	{
		return kth(tree[pos].r,k-tree[tree[pos].l].size-1);
	}
}

int pre(int val)
{
	int x,y;
	split(root,val-1,x,y);
	int ans=kth(x,tree[x].size);
	root=merge(x,y);
	return ans;
}

int suc(int val)
{
	int x,y;
	split(root,val,x,y);
	int ans=kth(y,1);
	root=merge(x,y);
	return ans;
}

int getrank(int val)
{
	int x,y;
	split(root,val-1,x,y);
	int ans=tree[x].size+1;
	root=merge(x,y);
	return ans;
}

signed main()
{
	int n=0,op=0,s=0;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>op>>s;
		if(op==1)
		{
			ins(s);
		}
		if(op==2)
		{
			del(s);
		}
		if(op==3)
		{
			cout<<getrank(s);
			if(i<n)cout<<endl;
		}
		if(op==4)
		{
			cout<<kth(root,s);
			if(i<n)cout<<endl;
		}
		if(op==5)
		{
			cout<<pre(s);
			if(i<n)cout<<endl;
		}
		if(op==6)
		{
			cout<<suc(s);
			if(i<n)cout<<endl;
		}
	}
	return 0;
}
相关推荐
旖旎夜光8 分钟前
LeetCode 215: 数组中的第K个最大元素 (快速排序) —— 题解
c++·学习·算法·leetcode·力控
技术胖14 分钟前
奎爷巡演 AIGC 视频教程 文档
算法
德彪稳坐倒骑驴1 小时前
Leetcode力扣刷题记录与题解
算法·leetcode·职场和发展
lzhdim7 小时前
AI的分类
人工智能·算法·机器学习·分类·数据挖掘
凤凰院凶涛QAQ10 小时前
《Java版数据结构 & 集合类剖析》Map & Set & 反射:“从哈希碰撞到红黑树转换,反射帮你扒开 HashMap 的桶数组看个究竟”
java·数据结构·算法
H.莓飛10 小时前
【数据结构】排序_OJ题(一):计数、桶与排序后的处理
java·开发语言·数据结构
w_zero_one12 小时前
算法--模拟
java·数据结构·算法
秋天的怀念_David12 小时前
算法一千零一夜 · 第十三夜 幻方,武侠世界里的数学迷宫
java·程序人生·算法
·present·12 小时前
CSAPP(lecture 4_01)
c语言·c++
FPGA小迷弟13 小时前
用 Claude Code 重构遗留系统:从评估到落地的完整实践指南
c++·python·ai·plotly·django·ai编程·claude