蒟蒻君的刷题日记Day4(线段树专题T1):CF19D Points

解题思路:线段树+平衡树

  • x , y x,y x,y这么大,为了不MLE,先离散化亿下。
  • 我们可以利用平衡树维护已标记点中每个 x x x对应所有 y y y的集合,每次查询能确定是否有符合条件的 x x x
  • 确定了 x x x,还要确定是否有符合条件的 y y y,这时我们就需要用到线段树,维护的是对于每个横坐标为 x x x的已标记点中 y y y的最大值。
  • 确定了有解,就可以用二分求出最优 x x x y y y啦~
  • 总结一下,这道题考察了较为模板的线段树与平衡树,只要注意细节,套好模板,难度并不大,作为紫题还是较水。

代码实现

#include <bits/stdc++.h>  
using namespace std;
const int N = 200005;
struct edge {
    int op, x, y;
} e[N];
struct Node{
    int l, r, maxv;
} node[4 * N];
int n, m, a[N];
set<int> s[N];
inline void pushup(int id) {
    node[id].maxv = max(node[id << 1].maxv, node[id << 1 | 1].maxv);
}
void build(int id, int l, int r) {
    node[id] = {l, r, -1};
    if (l == r) {
        return ;
    }
    int mid = l + r >> 1;
    build(id << 1, l, mid);
    build(id << 1 | 1, mid + 1, r);
}
void update(int id, int x) {
    int l = node[id].l, r = node[id].r;
    if (l == r) {
        node[id].maxv = s[x].size() ? *--s[x].end() : -1;
        return ;
    }
    int mid = l + r >> 1;
    if (x <= mid) {
        update(id << 1, x);
    } else {
        update(id << 1 | 1, x);
    }
    pushup(id);
}
int query(int id, int x, int y) {
    int l = node[id].l, r = node[id].r, maxv = node[id].maxv;
    if (r <= x || maxv <= y) {
        return -1;
    }
    if (l == r) {
        return l;
    }
    int resl = query(id << 1, x, y);
    return resl == -1 ? query(id << 1 | 1, x, y) : resl;
}
int main() {
    ios :: sync_with_stdio(0);
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        string S;
        cin >> S >> e[i].x >> e[i].y;
        e[i].op = S[0] == 'a' ? 1 : S[0] == 'r' ? 2 : 3;
        a[i] = e[i].x;
    }
    sort(a + 1, a + n + 1);
    int m = unique(a + 1, a + n + 1) - (a + 1);
    build(1, 1, n);
    for (int i = 1; i <= n; ++i) {
        int x = upper_bound(a + 1, a + m + 1, e[i].x) - (a + 1), y = e[i].y;
        if (e[i].op == 1) {
            s[x].insert(y);
            update(1, x);
        } else if (e[i].op == 2) {
            s[x].erase(y);
            update(1, x);
        } else {
            int res = query(1, x, y);
            if (res == -1) { 
                cout << -1 << '\n';
            } else {
                cout << a[res] << ' ' << *s[res].upper_bound(y) << '\n';
            }  
        }   
    }  
    return 0;
}

好好贺题,Day Day Up!!

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蒟蒻一枚

谢谢鸭~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值