zoukankan      html  css  js  c++  java
  • 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;
    }
    



  • 相关阅读:
    [SCOI2016] 幸运数字
    [CF438E] 小朋友和二叉树
    【题解】[AHOI2013]作业
    【题解】CF940F Machine Learning
    【题解】CF1207E XOR Guessing
    【题解】CF1228D Complete Tripartite
    【题解】CF1290B Irreducible Anagrams
    【题解】[JSOI2007]字符加密
    【题解】[SDOI2016]征途
    【题解】多边形染色
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3228530.html
Copyright © 2011-2022 走看看