Codeforces 19D Points
https://codeforces.com/problemset/problem/19/D
题意:
在二维平面上有三种操作:
- 1、增加一个点,保证不存在
- 2、去掉一个点,保证存在
- 3、询问 \((x,y)\) 右上角中最靠左中的最靠下的点的位置
题解:
首先非常显然将操作进行离线,离散化它的坐标,坐标可以按优先横坐标排序,当然这个不关键。考虑如何维护右边最低点,实际上使用线段树即可,我们按优先横坐标进行离散化建立线段树,则询问 \(i\) 这个点右边这一条件就变成了在 (i,n] 中寻找解,很轻松的发现这个是满足二分性质的,我们相当于是要找到最小的 \(j\),使得 \(max(y_{i+1} \to y_j) > y_i\),直接在线段树上二分可以做到单次 log 复杂度,由于是 well-known 的线段树二分操作不做证明,如果是二分套线段树则是双 log 复杂度。
然后 1,2 两种操作显然并不复杂,维护一个区间 max 即可。
代码:
/*================================================================
*
* 文件名称:A.cpp
* 创 建 者: badcw
* 创建日期:2019年05月01日
*
================================================================*/
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e5+5;
const int mod = 998244353;
ll qp(ll a, ll n) {
ll res = 1;
while (n > 0) {
if (n & 1) res = res * a % mod;
a = a * a % mod;
n >>= 1;
}
return res;
}
template <class T>
inline bool scan(T& ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return 0; // EOF
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
template <class T>
inline void out(T x) {
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
struct op {
int stat, x, y;
}p[maxn];
int n;
struct point {
int x, y;
bool operator < (const point& oth) const {
if (x != oth.x) return x < oth.x;
return y < oth.y;
}
bool operator == (const point& oth) const {
return x == oth.x && y == oth.y;
}
};
vector<point> st;
int val[maxn << 2];
int le, re, k;
void update(int rt, int l, int r) {
if (l == r) {
val[rt] = k;
return;
}
int mid = l + r >> 1;
if (le <= mid) update(rt << 1, l, mid);
else update(rt << 1 | 1, mid + 1, r);
val[rt] = max(val[rt << 1], val[rt << 1 | 1]);
}
int query(int rt, int l, int r) {
if (val[rt] <= st[k].y || st[r].x <= st[k].x) {
return -1;
}
if (l == r) {
return l;
}
int mid = l + r >> 1;
int res = query(rt << 1, l, mid);
if (res == -1) res = query(rt << 1 | 1, mid + 1, r);
return res;
}
int main()
{
scanf("%d", &n);
char sta[7];
for (int i = 1; i <= n; ++i) {
scanf("%s%d%d", sta, &p[i].x, &p[i].y);
p[i].y ++;
if (sta[0] == 'a') p[i].stat = 1;
else if (sta[0] == 'r') p[i].stat = 2;
else p[i].stat = 3;
st.push_back({p[i].x, p[i].y});
}
st.push_back({0, 0});
sort(st.begin(), st.end());
st.erase(unique(st.begin(), st.end()), st.end());
st.push_back({1000000000, 1000000000});
// for (int i = 0; i < st.size(); ++i) {
// printf("*%d %d\n", st[i].x, st[i].y);
// }
int sz = st.size() - 1;
for (int i = 1; i <= n; ++i) {
if (p[i].stat == 1) {
le = lower_bound(st.begin(), st.end(), point{p[i].x, p[i].y}) - st.begin();
k = p[i].y;
update(1, 1, sz);
} else if (p[i].stat == 2) {
le = lower_bound(st.begin(), st.end(), point{p[i].x, p[i].y}) - st.begin();
k = 0;
update(1, 1, sz);
} else {
k = lower_bound(st.begin(), st.end(), point{p[i].x, p[i].y}) - st.begin();
int res = query(1, 1, sz);
if (res == -1) printf("-1\n");
else printf("%d %d\n", st[res].x, st[res].y - 1);
}
}
return 0;
}