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\n", A[t-1], *a[t].upper_bound(y));

            else puts("-1");

        }

    }



    return 0;

}


 


 

你可能感兴趣的:(poi)