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