参考的大佬的博客的链接:
https://blog.csdn.net/onepointo/article/details/75083305
//luogu_3369
#include <stdio.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long LL;
<LL, null_type, less<LL>, rb_tree_tag, tree_order_statistics_node_update> t;
tree<int, int> ma;
mapvoid Insert(int v) {
.insert(((LL)v << 32) + ++ma[v]);
t}
void Delete(int v) {
auto it = ma.find(v);
.erase(((LL)v << 32) + it->second);
t--it->second;
if (0 == it->second) {
.erase(it);
ma}
}
int RankOf(int v) {
return t.order_of_key((LL)v << 32) + 1;
}
int FindByRank(int r) {
return *t.find_by_order(r-1) >> 32;
}
int FindPre(int v) {
auto it = ma.lower_bound(v);
--it;
return it->first;
}
int FindNext(int v) {
return ma.upper_bound(v)->first;
}
int main() {
int n;
("%d", &n);
scanfwhile (n--) {
int op, x;
("%d%d", &op, &x);
scanfswitch (op) {
case 1:
(x);
Insertbreak;
case 2:
(x);
Deletebreak;
case 3:
("%d\n", RankOf(x));
printfbreak;
case 4:
("%d\n", FindByRank(x));
printfbreak;
case 5:
("%d\n", FindPre(x));
printfbreak;
case 6:
("%d\n", FindNext(x));
printfbreak;
}
}
return 0;
}
注意如果less<LL>不小心写成了less<int>,编译器不会报错,但是答案是错的。
另一种不用map来求前驱和后继的比较和谐的方法:
//luogu_3369
#include <stdio.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long LL;
<LL, null_type, less<LL>, rb_tree_tag, tree_order_statistics_node_update> t;
tree<int, int> ma;
mapvoid Insert(int v) {
.insert(((LL)v << 32) + ++ma[v]);
t}
void Delete(int v) {
.erase(((LL)v << 32) + ma[v]--);
t}
int RankOf(int v) {
return t.order_of_key((LL)v << 32) + 1;
}
int FindByRank(int r) {
return *t.find_by_order(r-1) >> 32;
}
int FindPre(int v) {
auto it = t.lower_bound((LL)v << 32);
--it;
return *it >> 32;
}
int FindNext(int v) {
return *t.lower_bound((LL)(v+1) << 32) >> 32;
}
int main() {
int n;
("%d", &n);
scanfwhile (n--) {
int op, x;
("%d%d", &op, &x);
scanfswitch (op) {
case 1:
(x);
Insertbreak;
case 2:
(x);
Deletebreak;
case 3:
("%d\n", RankOf(x));
printfbreak;
case 4:
("%d\n", FindByRank(x));
printfbreak;
case 5:
("%d\n", FindPre(x));
printfbreak;
case 6:
("%d\n", FindNext(x));
printfbreak;
}
}
return 0;
}
封装版:
//luogu_3369
#include <stdio.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
template<typename T, typename less>
struct Cmp_MultiSet {
bool operator () (const pair<T, size_t>& x, const pair<T, size_t>& y) const {
return less()(x.first, y.first) ? true : (less()(y.first, x.first) ? false : less()(x.second, y.second));
}
};
template<typename T, typename less>
struct MultiSet {
<pair<T, size_t>, null_type, Cmp_MultiSet<T, less>, rb_tree_tag, tree_order_statistics_node_update> t;
tree<T, size_t> ma;
mapvoid Insert(T v) {
.insert(make_pair(v, ++ma[v]));
t}
void Delete(T v) {
.erase(make_pair(v, ma[v]--));
t}
size_t RankOf(T v) {
return t.order_of_key(make_pair(v, 0)) + 1;
}
(size_t r) {
T FindByRankreturn t.find_by_order(r-1)->first;
}
(T v) {
T FindPreauto it = t.lower_bound(make_pair(v, 0));
return (--it)->first;
}
(T v) {
T FindNextreturn t.lower_bound(make_pair(v+1, 0))->first;
}
};
int main() {
<int, less<int> > se;
MultiSetint n;
("%d", &n);
scanfwhile (n--) {
int op, x;
("%d%d", &op, &x);
scanfswitch (op) {
case 1:
.Insert(x);
sebreak;
case 2:
.Delete(x);
sebreak;
case 3:
("%lu\n", se.RankOf(x));
printfbreak;
case 4:
("%d\n", se.FindByRank(x));
printfbreak;
case 5:
("%d\n", se.FindPre(x));
printfbreak;
case 6:
("%d\n", se.FindNext(x));
printfbreak;
}
}
return 0;
}