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;
}
posted @ 2020-06-16 17:27  badcw  阅读(156)  评论(0编辑  收藏  举报