bzoj 2028 [SHOI2009]会场预约 set

题面

题目传送门

解法

简单的STL应用

  • 考虑一下前面的线段[l,r]会在什么时候与当前线段[l,r]冲突,显然,只要满足rl,lr的条件就可以说明这两条线段有交
  • 所以,我们可以开一个set来维护前面的若干条线段,每一次加入一条线段的时候先找到右端点大于l的线段,然后一个一个扫过去,能删就删
  • 看起来这个程序挺暴力的,似乎是O(q2logq)??
  • 但是并非如此,因为每一条线段最多只会在set里出现一次,被删掉一次,所以均摊下来删除的复杂度是O(logq)
  • 时间复杂度:O(qlogq)
  • 当然,本题也可以使用线段树,平衡树之类的,但是码量较大不太建议

代码

#include <bits/stdc++.h>
using namespace std;
template <typename node> void chkmax(node &x, node y) {x = max(x, y);}
template <typename node> void chkmin(node &x, node y) {x = min(x, y);}
template <typename node> void read(node &x) {
    x = 0; int f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
    while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
struct Node {
    int l, r;
    bool operator < (const Node &a) const {
        if (r == a.r) return l < a.l;
        return r < a.r;
    }
};
int main() {
    int q; read(q);
    set <Node> s;
    while (q--) {
        char key = getchar();
        while (!isalpha(key)) key = getchar();
        if (key == 'A') {
            int l, r, ans = 0; read(l), read(r);
            while (1) {
                set <Node> :: iterator it = s.lower_bound((Node) {0, l});
                if (it != s.end() && it->l <= r) s.erase(it), ans++;
                    else break;
            }
            s.insert((Node) {l, r}); cout << ans << "\n";
        } else cout << s.size() <<"\n";
    }
    return 0;
}
发布了94 篇原创文章 · 获赞 2 · 访问量 6980
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览