「LuoguP3369」 【模板】普通平衡树 (用vector乱搞平衡树
Description
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入 x 数
- 删除 x 数(若有多个相同的数,应只删除一个)
- 查询 x 数的排名(排名定义为比当前数小的数的个数 。若有多个相同的数,因输出最小的排名)
- 查询排名为 x 的数
- 求 x 的前驱(前驱定义为小于 x ,且最大的数)
- 求 x 的后继(后继定义为大于 x ,且最小的数)
Input
第一行为 n ,表示操作的个数,下面 n 行每行有两个数 opt 和 x , opt 表示操作的序号( 1≤opt≤6 )
Output
对于操作 3,4,5,6 每行输出一个数,表示对应答案
Sample Input
10 1 106465 4 1 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598
Sample Output
106465 84185 492737
Hint
时空限制:1000ms,128M
1.n的数据范围: n≤100000
2.每个数的数据范围: [−107,107][-{10}^7, {10}^7]
来源:Tyvj1728 原名:普通平衡树
在此鸣谢
题解
这里用的是vector
参(xue)考(xi)资料:Rye_Catcher的题解 ;C++ vector用法_金河
因为实在搞不清楚treap的旋转(令人头大 所以选择了万能的STL
其实vector并不是有序的,但是我们可以自行维护vector的有序性。
前置知识:(时间复杂度也不太确定 有问题希望大佬纠正
- 定义:vector<int>a; 需<vector>头文件
- 访问元素:a[x] 取出a中的第(x+1)个数(下标从0开始 O(1)
- a.begin():返回起始元素的迭代器 O(1)
- a.end():返回终止元素的迭代器 O(1)
- a.insert(a.begin()+pos,x):在第pos个数后面插入x O(n)
- a.erase(a.begin()+pos):删除pos位置的数 pos之后的数自动补齐 O(n)
- lower_bound(a.begin(),a.end(),x)返回第一个==x的位置的迭代器 O(logn)
- upper_bound(a.begin(),a.end(),x)返回最后一个==x的位置的后面一个的迭代器(x的后继 O(logn)
- *it:取出迭代器it中的值(大概只有我不知道
然后 你应该自己就懂了(嘿嘿嘿
对着代码理解吧
1 #include<algorithm> 2 #include<iostream> 3 #include<vector> 4 using namespace std; 5 vector<int>a; 6 int main() 7 { 8 int n; 9 cin>>n; 10 for(int i=1;i<=n;++i) 11 { 12 int opt,x; 13 scanf("%d%d",&opt,&x); 14 switch(opt) 15 { 16 case(1):a.insert(upper_bound(a.begin(),a.end(),x),x);break;//插入 17 case(2):a.erase(lower_bound(a.begin(),a.end(),x));break;//删除 18 case(3):cout<<lower_bound(a.begin(),a.end(),x)-a.begin()+1<<endl;break;//输出x的排名 19 case(4):cout<<a[x-1]<<endl;break;//输出第x的数 20 case(5):cout<<*--lower_bound(a.begin(),a.end(),x)<<endl;break;//x的前趋 21 case(6):cout<<*upper_bound(a.begin(),a.end(),x)<<endl;break;//x的后继 22 } 23 } 24 return 0; 25 }
UPD
新学的set,但是支持的操作肽少了qwq
关于排名的只能用很慢的distance($O(n)$)和advance($O(n)$)qwq
然后还是照着之前那篇题解学的。
嗯。
1 /* 2 qwerta 3 P3369 【模板】普通平衡树 Unaccepted 4 64 5 代码 C++,0.57KB 6 提交时间 2018-10-31 21:39:58 7 耗时/内存 5756ms, 2820KB 8 */ 9 #include<iostream> 10 #include<cstdio> 11 #include<set> 12 using namespace std; 13 multiset<int>s; 14 int main() 15 { 16 //freopen("a.in","r",stdin); 17 int n; 18 scanf("%d",&n); 19 while(n--) 20 { 21 int opt,x; 22 scanf("%d%d",&opt,&x); 23 switch(opt) 24 { 25 case(1):s.insert(x);break; 26 case(2):s.erase(s.lower_bound(x));break; 27 case(3):cout<<distance(s.begin(),s.lower_bound(x))+1<<endl;break; 28 case(4):{multiset<int>::iterator it=s.begin(); 29 advance(it,x-1);cout<<(*it)<<endl;break;} 30 case(5):cout<<(*--s.lower_bound(x))<<endl;break; 31 case(6):cout<<(*s.upper_bound(x))<<endl;break; 32 } 33 } 34 return 0; 35 }