Codeforces 19D - Points (线段树 + set)

题意:在一个二维平面上 有三种操作

   1.添加一个点

   2.删去一个点

   3.询问严格在(x, y)右上的点 先取最左 然后最低的

题解:先把x离散化 然后用线段树维护横坐标为x的最大值 同样把每个x开一个set 就可以处理添加和删除操作了

   询问(x, y) 就是在横坐标大于x的区域 求第一个最大值大于y的x 然后我们就可以在x这个set里找第一个大于y的点了

   注意好好写询问 单次是$log$的

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <set>
using namespace std;
const int MAXN = 2e5 + 5;
const int INF = 0x3f3f3f3f;
int T, cnt;
char s[25];
int opt[MAXN], x[MAXN], y[MAXN];
int b[MAXN];
set<int> st[MAXN];

int zd[MAXN << 2];
void pushup(int rt) {
    zd[rt] = max(zd[rt << 1], zd[rt << 1 | 1]);
}

void update(int k, int v, int l, int r, int rt) {
    if(l == r) {
        zd[rt] = max(zd[rt], v);
        return;
    }

    int mid = (l + r) >> 1;
    if(k <= mid) update(k, v, l, mid, rt << 1);
    else update(k, v, mid + 1, r, rt << 1 | 1);
    pushup(rt);
}

void change(int k, int v, int l, int r, int rt) {
    if(l == r) {
        zd[rt] = v;
        return;
    }

    int mid = (l + r) >> 1;
    if(k <= mid) change(k, v, l, mid, rt << 1);
    else change(k, v, mid + 1, r, rt << 1 | 1);
    pushup(rt);
}

int find(int pos, int v, int l, int r, int rt) {
    if(pos > cnt) return 0;
    if(zd[rt] <= v) return 0;
    if(l == r) return l;

    int mid = (l + r) >> 1;
    if(pos > mid) return find(pos, v, mid + 1, r, rt << 1 | 1);
    else {
        int res = 0;
        res = find(pos, v, l, mid, rt << 1);
        if(res < pos) res = find(pos, v, mid + 1, r, rt << 1 | 1);
        return res;
     }
}


int main() {
    scanf("%d", &T);
    for(int i = 1; i <= T; i++) {
        scanf("%s", s + 1);
        if(s[1] == 'a') opt[i] = 1;
        else if(s[1] == 'r') opt[i] = 2;
        else opt[i] = 3;
        scanf("%d%d", &x[i], &y[i]);
        b[++cnt] = x[i];
    }
    sort(b + 1, b + 1 + cnt);
    cnt = unique(b + 1, b + 1 + cnt) - (b + 1);

    for(int i = 1; i <= T; i++) {
        int t = lower_bound(b + 1, b + 1 + cnt, x[i]) - b;
        
        if(opt[i] == 1) {
            st[t].insert(y[i]);
            update(t, y[i], 1, cnt, 1);
        } else if(opt[i] == 2) {
            set<int>::iterator it;
            it = st[t].lower_bound(y[i]);
            st[t].erase(*it);
            if(!st[t].size()) change(t, 0, 1, cnt, 1);
            else change(t, *st[t].end(), 1, cnt, 1);
        } else {
            int res = find(t + 1, y[i], 1, cnt, 1);
            if(res == 0) puts("-1");
            else {
                set<int>::iterator it;
                it = st[res].upper_bound(y[i]);
                printf("%d %d\n", b[res], *it);
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2020-04-29 21:06  lwqq3  阅读(177)  评论(0编辑  收藏  举报