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;
}
相关推荐
老洋葱Mr_Onion10 小时前
【C++】信息学奥赛CSP通关之路——CSP-J/S第一轮原创全真模拟试卷集(2026)卷四全卷解析
开发语言·c++
zander25810 小时前
LeetCode 739:每日温度——为什么单调栈要持续弹出
开发语言·python·算法
2601_9557598810 小时前
如何降低 Claude API 批量生产返工率
大数据·人工智能·算法
rannn_11111 小时前
【力扣hot100】链表专题下|138、148、23、146
java·算法·leetcode·链表·开发
ly768911 小时前
分布式一致性算法详解:从 2PC、3PC 到 Paxos、Raft、ZAB
分布式·算法
阿维的博客日记11 小时前
保姆级教程-BBPE分词算法
算法·bbpe
不会就选b12 小时前
算法日常・每日刷题--<优先级队列>2
数据结构·算法
hanlin0312 小时前
刷题笔记:力扣第189题-轮转数组
笔记·算法·leetcode
琥珀色糖12 小时前
leetcode hot100题(持续更新)移动零(双指针)
算法·leetcode·职场和发展·双指针·移动零
小小龙学IT12 小时前
simdjson:利用 SIMD 指令实现 GB/s 级 JSON 解析的 C++ 开源库
开发语言·c++·json