P3369

【模板】普通平衡树

题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

  1. 插入 \(x\)
  2. 删除 \(x\) 数(若有多个相同的数,因只删除一个)
  3. 查询 \(x\) 数的排名(排名定义为比当前数小的数的个数 \(+1\) )
  4. 查询排名为 \(x\) 的数
  5. \(x\) 的前驱(前驱定义为小于 \(x\),且最大的数)
  6. \(x\) 的后继(后继定义为大于 \(x\),且最小的数)

输入格式

第一行为 \(n\),表示操作的个数,下面 \(n\) 行每行有两个数 \(\text{opt}\)\(x\)\(\text{opt}\) 表示操作的序号( $ 1 \leq \text{opt} \leq 6 $ )

输出格式

对于操作 \(3,4,5,6\) 每行输出一个数,表示对应答案

样例 #1

样例输入 #1

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

样例输出 #1

106465
84185
492737

提示

【数据范围】
对于 \(100\%\) 的数据,\(1\le n \le 10^5\)\(|x| \le 10^7\)

pbds实现平衡树
因为tree中不能有相同元素所以<<20后加上时间戳不影响相对大小又能还原成原来的数据
这样处理的话 每个x<<20+i就构成相同元素的集合
找前驱:lower_bound((x<<20)+1)
找后驱:upper_bound((x<<20)+n)
注意位运算的优先级低!!!
点击查看代码
#include<bits/stdc++.h>
#include<ext/rope>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_cxx;
using namespace __gnu_pbds;
typedef long long ll;
tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>tr;//红黑树
int n;
signed main()
{
	ios::sync_with_stdio(false);	
	cin>>n;
	for(ll i=1;i<=n;i++)
	{
		ll opt,x;
		cin>>opt>>x;
		if(opt==1)
			tr.insert((x<<20)+i);//因为tree中不能有相同元素所以<<20后加上时间戳不影响相对大小又能还原成原来的数据 
		if(opt==2)
			tr.erase(tr.lower_bound((x<<20)+1));
		if(opt==3)
			cout<<tr.order_of_key(x<<20)+1<<"\n";//order是从0开始的所以要+1 
		if(opt==4){ll ans=*tr.find_by_order(x-1);cout<<(ans>>20)<<"\n";}//还愿成原始数据
		if(opt==5){ll ans=*--tr.lower_bound((x<<20)+1);cout<<(ans>>20)<<"\n";}//用STL找前驱套路
		if(opt==6){ll ans=*tr.upper_bound((x<<20)+n);cout<<(ans>>20)<<"\n";} //相同的数的处理 
	}
	return 0; 
} 
背头文件 tree的创建格式!
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>tr
posted @ 2023-01-16 23:15  PKU_IMCOMING  阅读(8)  评论(0)    收藏  举报