文章目录
解题思路:线段树+平衡树
- x , y x,y x,y这么大,为了不MLE,先离散化亿下。
- 我们可以利用平衡树维护已标记点中每个 x x x对应所有 y y y的集合,每次查询能确定是否有符合条件的 x x x。
- 确定了 x x x,还要确定是否有符合条件的 y y y,这时我们就需要用到线段树,维护的是对于每个横坐标为 x x x的已标记点中 y y y的最大值。
- 确定了有解,就可以用二分求出最优 x x x和 y y y啦~
- 总结一下,这道题考察了较为模板的线段树与平衡树,只要注意细节,套好模板,难度并不大,作为紫题还是较水。
代码实现
#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
struct edge {
int op, x, y;
} e[N];
struct Node{
int l, r, maxv;
} node[4 * N];
int n, m, a[N];
set<int> s[N];
inline void pushup(int id) {
node[id].maxv = max(node[id << 1].maxv, node[id << 1 | 1].maxv);
}
void build(int id, int l, int r) {
node[id] = {l, r, -1};
if (l == r) {
return ;
}
int mid = l + r >> 1;
build(id << 1, l, mid);
build(id << 1 | 1, mid + 1, r);
}
void update(int id, int x) {
int l = node[id].l, r = node[id].r;
if (l == r) {
node[id].maxv = s[x].size() ? *--s[x].end() : -1;
return ;
}
int mid = l + r >> 1;
if (x <= mid) {
update(id << 1, x);
} else {
update(id << 1 | 1, x);
}
pushup(id);
}
int query(int id, int x, int y) {
int l = node[id].l, r = node[id].r, maxv = node[id].maxv;
if (r <= x || maxv <= y) {
return -1;
}
if (l == r) {
return l;
}
int resl = query(id << 1, x, y);
return resl == -1 ? query(id << 1 | 1, x, y) : resl;
}
int main() {
ios :: sync_with_stdio(0);
cin >> n;
for (int i = 1; i <= n; ++i) {
string S;
cin >> S >> e[i].x >> e[i].y;
e[i].op = S[0] == 'a' ? 1 : S[0] == 'r' ? 2 : 3;
a[i] = e[i].x;
}
sort(a + 1, a + n + 1);
int m = unique(a + 1, a + n + 1) - (a + 1);
build(1, 1, n);
for (int i = 1; i <= n; ++i) {
int x = upper_bound(a + 1, a + m + 1, e[i].x) - (a + 1), y = e[i].y;
if (e[i].op == 1) {
s[x].insert(y);
update(1, x);
} else if (e[i].op == 2) {
s[x].erase(y);
update(1, x);
} else {
int res = query(1, x, y);
if (res == -1) {
cout << -1 << '\n';
} else {
cout << a[res] << ' ' << *s[res].upper_bound(y) << '\n';
}
}
}
return 0;
}
好好贺题,Day Day Up!!