CF Beta Round #19 D. Points(线段树+离散化)

链接

http://codeforces.com/contest/19/problem/D

题意

给定n个操作,共有3种操作

  1. add x y
    向坐标系中添加点(x,y)
  2. del x y
    向坐标系中删除点(x,y)
  3. find x y
    在坐标系中找到一点(x0,y0),满足x0>x and y0>y,如果有多个满足的,优先考虑x0最小,其次y0最小,输出这个点,如果不存在这样的点,输出-1;
分析

这里使用线段树,首先x,y均是1E9,考虑对x进行离散化,并以离散后的x建立一个线段树,线段树的一个节点[l,r]存储着离散后区间为[l,r]的信息,定义着一个max,代表当前区间所有点坐标的最大的y,若当前区间左子区间的max大于我们给的y,那么就进去看看找到的结果可不可行(y满足x可能不满足),不可行就进行右子区间的查找;还需要定义着一个set数组,set[a]中存储a没离散之前所对应的所有y坐标(可能存在一部分点x坐标相同,y坐标不同)当进行find x y操作时,首先lower_bound+1或upper_bound查询大于x的值,最后找到合适的set,在upper_bound即可;

代码
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <string>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <set>
    #include <map>
     
    using namespace std;
     
    #define inf 0x7f7f7f7f
    #define maxn 200005
    #define N 200005
    #define P 2
    typedef long long ll;
     
    int n, k, a[maxn], cnt;
     
    char s[maxn][7];
    int valx[maxn], valy[maxn];
     
    struct Tree {
        int l, r, max;
    } tree[4 * maxn];
     
    inline void push_up(int x) {
        tree[x].max = max(tree[x << 1].max, tree[x << 1 | 1].max);
    }
     
    set<int> st[maxn];
     
    void build(int x, int l, int r) {
        tree[x].l = l, tree[x].r = r, tree[x].max = 0;
        if (l == r)return;
        int mid = (l + r) >> 1;
        build(x << 1, l, mid);
        build(x << 1 | 1, mid + 1, r);
        push_up(x);
    }
     
    void update(int x, int pos, int val) {
        int l = tree[x].l, r = tree[x].r;
        if (l == r) {
            st[pos].insert(val);
            tree[x].max = *--st[pos].end();
            return;
        }
        int mid = (l + r) >> 1;
        if (pos <= mid)update(x << 1, pos, val);
        else update(x << 1 | 1, pos, val);
        push_up(x);
    }
     
    void del(int x, int pos, int val) {
        int l = tree[x].l, r = tree[x].r;
        if (l == r) {
            st[l].erase(val);
            tree[x].max = st[l].empty() ? 0 : *--st[l].end();
            return;
        }
        int mid = (l + r) >> 1;
        if (pos <= mid)del(x << 1, pos, val);
        else del(x << 1 | 1, pos, val);
        push_up(x);
    }
     
    pair<int, int> find(int x, int pos, int val) {
        //cout << tree[x].max <<" " << val <<" " << tree[x].l <<" " <<x<<endl;
        int l = tree[x].l, r = tree[x].r;
        if(tree[x].max <= val || r < pos){
            return make_pair(-1,0);
        }
        if (l == r){
            return make_pair(l, *st[l].upper_bound(val));
        }
        int mid = (l + r) >> 1;
        pair <int, int> p= find(x << 1, pos, val);
        if (p.first != -1) return p;
        return find(x << 1 | 1, pos, val);
    }
     
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%s%d%d", s[i], &valx[i], &valy[i]);
            a[++cnt] = valx[i];
        }
        sort(a + 1, a + 1 + cnt);
        int len = unique(a + 1, a + 1 + cnt) - a - 1;
        build(1, 1, len);
        for (int i = 1; i <= n; i++) {
            if (s[i][0] == 'a') {
                int pos = lower_bound(a + 1, a + 1 + len, valx[i]) - a;
                update(1, pos, valy[i]);
            } else if (s[i][0] == 'r') {
                int pos = lower_bound(a + 1, a + 1 + len, valx[i]) - a;
                del(1, pos, valy[i]);
            } else {
                int pos = upper_bound(a + 1, a + 1 + len, valx[i]) - a;
                pair<int, int> p = find(1, pos, valy[i]);
                if(p.first == -1) {
                    cout << -1 <<endl;
                    continue;
                }
                cout << a[p.first] << " " << p.second <<endl;
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值