P3369
【模板】普通平衡树
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入 \(x\) 数
- 删除 \(x\) 数(若有多个相同的数,因只删除一个)
- 查询 \(x\) 数的排名(排名定义为比当前数小的数的个数 \(+1\) )
- 查询排名为 \(x\) 的数
- 求 \(x\) 的前驱(前驱定义为小于 \(x\),且最大的数)
- 求 \(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
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号