维护点的方式非常简单,就像是奶牛那道题,二维转一维。
坐标离散化是必须的,用线段树来维护y坐标的大小关系,然后把x坐标当成区间,也就是说,我们是把x坐标当成了线段树的区间,y坐标当成了线段树的权值,这样的话就可以维护某一个x坐标上y坐标最大的点是多少。然后插入或者的时候直接二分出来x的位置,然后插入或者删除就行了,查询的时候让我稍稍拐了点儿弯儿,实际上就是用查询的点的x坐标定位线段树上的位置,然后对于位置查权值来确定y坐标是否符合,询问到叶子节点就是答案,如果走不到叶子节点,那就是没有答案。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
const int maxn = 200000 + 10;
int flag[maxn], tree[maxn << 3];
struct point{
int x, y;
bool operator < (const point& a) const{
if (x != a.x) return x < a.x;
return y < a.y;
}
}a[maxn], x[maxn], ans, null;
void PushUp(int rt){
tree[rt] = max(tree[rt << 1], tree[rt << 1 | 1]);
}
void update(bool f, int X, int p, int l, int r, int rt){
if (l == r){
tree[rt] = f ? p : -1;
return;
}
int m = (l + r) >> 1;
if (X <= m) update(f, X, p, lson);
else update(f, X, p, rson);
PushUp(rt);
}
void query(point p, int l, int r, int rt){
if (x[r].x <= p.x || tree[rt] <= p.y) return;
if (l == r) ans = x[l];
int m = (l + r) >> 1;
query(p, lson);
if (ans.x == -1) query(p, rson);
}
int main(){
// freopen("in", "r", stdin);
memset(tree, -1, sizeof(tree));
int n, i, m = 0;
null.x = null.y = -1;
char op[10];
scanf("%d", &n);
for (int i = 0; i < n; i++){
scanf("%s%d%d", op, &a[i].x, &a[i].y);
if (op[0] == 'a'){
x[m++] = a[i]; flag[i] = 1;
}else if (op[0] == 'f'){
x[m++] = a[i]; flag[i] = 2;
}
else flag[i] = 0;
}
sort(x, x + m);
for (i = 0; i < n; i++){
int now = lower_bound(x, x + m, a[i]) - x;
if (flag[i] < 2) update(flag[i], now, a[i].y, 0, m - 1, 1);
else{
ans = null;
query(a[i], 0, m - 1, 1);
if (ans.x == -1) puts("-1");
else printf("%d %d\n", ans.x, ans.y);
}
}
return 0;
}