链接1:https://www.luogu.com.cn/problem/P5076
链接2:https://www.luogu.com.cn/problem/P3369
综合题意:给定n个操作(n<=1e5)。
1.查询x的排名
2.查询排名为x的数
3.求x的前驱(若无则输出-2147483647)
4.求x的后继(若无则输出2147483647)
5.插入x
6.删除x
所有数都在1e9以内。
题解:无疑是考察二叉树的模板问题,我们这里用vector来操作(之后也可以这样子用),下标从0开始
总结:1.vector更是严格的“二叉树”,不会“退化”,复杂度一般稳定在O(logn)。唯一的缺点就是插入的时候时间复杂度最坏是O(n)的。
2.二叉树这些操作比这个麻烦太多了,明天有时间的话再来研究下完全用二叉排序树来实现吧。
3.可能最强的是set+数组+树状数组/线段树吧
代码:
struct two {
vector<ll> v;
vector<ll>::iterator p;
//1.返回 x的排名,时间复杂度为O(logn)
ll queryrnk(ll x) {
return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
//2.返回排名为x的数,时间复杂度为O(1)
ll querykth(ll x) {
return v[x-1];
}
//3.返回x的前驱,若没找到则输出-inf,时间复杂度为O(logn)
//注意前驱后继为二叉树上的,而非数组上的,差别在于,二叉树上无重复
ll get_pre(ll x) {
p=lower_bound(v.begin(),v.end(),x);//先找x
if(p==v.begin()) return -inf;//最差为v.begin()
else return *(p-1);
}
//4.返回x的后缀,若没找到则输出inf,时间复杂度为O(logn)
ll get_nxt(ll x) {
p=upper_bound(v.begin(),v.end(),x);
if(p==v.end()) return inf;
else return *p;//注意不是*(p+1)
}
//5.插入x,时间复杂度为线性,最坏O(n)
void insert(ll x) {
v.insert(upper_bound(v.begin(),v.end(),x),x);//从后往前移,upper更好
//v.insert::在某个迭代器的位置插入某个元素,时间复杂度与插入位置后面的数的个数有关
}
//6.删除x,时间复杂度与insert一样
void erase(ll x){
v.erase(lower_bound(v.begin(),v.end(),x));//删除某迭代器位置的数,复杂度与insert一样
}
}T;