CF 19D Points 【线段树+平衡树】

在平面上进行三种操作:

1、add x y:在平面上添加一个点(x,y)

2、remove x y:将平面上的点(x,y)删除

3、find x y:在平面上寻找一个点,使这个点的横坐标大于x,纵坐标大于y,而且要求他的横坐标尽量小,如果有多个点满足,则选取横坐标尽量小的前提下,纵坐标最小的点。


方法:

将横坐标x离散化,每一个坐标x对应的y用一颗平衡树维护(C++中的set),则这颗平衡树支持增加和删除以及查找比y大的最小值的操作。


在此基础上,对于每一个询问,只需要遍历大于x的set,并且找到最小的y即可。但是这样子依次向后遍历的复杂度为O(N)的,所以要用一颗线段树来维护横坐标区间段里面y的最大值,这样就可以在O(logN)的复杂度内找到最接近x的横坐标(而且满足当前坐标的最大纵坐标大于y),然后再set里面查找最小的纵坐标即可。



#include <cstdio>
#include <vector>
#include <set>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 200100
int n, m, A[N], my[N<<2];
set<int> a[N];
char s[10];

struct node {
    char op;
    int x, y;
} q[N];

int idx(int v) {
    return lower_bound(A, A+m, v) - A + 1;
}

void update(int x, int L, int R, int rt) {
    if (L == R) {
        if (a[x].size() == 0) my[rt] = 0;
        else my[rt] = *a[x].rbegin();
        return ;
    }
    int Mid = (L + R) >> 1;
    if (x <= Mid) update(x, L, Mid, rt<<1);
    else update(x, Mid+1, R, rt<<1|1);
    my[rt] = max(my[rt<<1], my[rt<<1|1]);
}
int query(int x, int y, int L, int R, int rt) {
    if (L == R) {
        if (my[rt] > y && x < L) return L;
        return 0;
    }

    int Mid = (L + R) >> 1;
    int t = 0;
    if (x < Mid && my[rt<<1] > y) t = query(x, y, L, Mid, rt<<1);
    if (t == 0 && my[rt<<1|1] > y) t = query(x, y, Mid+1, R, rt<<1|1);
    return t;
}
int main() {
    scanf("%d", &n);
    m = 0;
    for (int i=0; i<n; i++) {
        scanf(" %s%d%d", s, &q[i].x, &q[i].y);
        q[i].op = s[0];
        A[m++] = q[i].x;
        a[i].clear();
    }
    a[n].clear();

    sort(A, A+m);
    m = unique(A, A+m) - A;

    memset(my, 0, sizeof(my));
    int x, y;
    for (int i=0; i<n; i++) {
        x = idx(q[i].x), y = q[i].y;

        if (q[i].op == 'a') {
            a[x].insert(y);
            update(x, 1, n, 1);
        } else if (q[i].op == 'r') {
            a[x].erase(y);
            update(x, 1, n, 1);
        } else {
            int t = query(x, y, 1, n, 1);
            if (t) printf("%d %d
", A[t-1], *a[t].upper_bound(y));
            else puts("-1");
        }
    }

    return 0;
}



原文地址:https://www.cnblogs.com/dyllove98/p/3228530.html