题目大意:
有
n
n
n个操作总数,每个操作有
2
2
2种:
①
A
A
A操作:给出区间
[
s
t
a
r
t
,
e
n
d
]
[start,end]
[start,end],把前面冲突的区间(有交集)去掉,并输出去掉的区间总数
②
B
B
B操作:返回当前的仍然有效的预约的总数。
N
<
=
200000
N< = 200000
N<=200000
1
<
=
s
t
a
r
t
,
e
n
d
<
=
100000
1< = start,end < = 100000
1<=start,end<=100000
分析:
对于第
i
i
i个操作而言,
如果是
A
A
A,那么我们将前面的区间排序,以
e
n
d
end
end升序排列,
e
n
d
end
end相等时
s
t
a
r
t
start
start升序排列,对于当前的区间
[
l
,
r
]
[l,r]
[l,r],我们二分出
[
0
,
l
]
[0,l]
[0,l]在这个序列中的位置,即放进去以后能满足前面的要求,那么此时我们就能保证
l
l
l小于等于所在位置及后面的位置的
r
r
r,此时如果满足
r
r
r大于等于它们的
l
l
l,则区间有交集,将这些区间去掉并统计个数即可,然后如果做到某一个以后没交集了,后面也不会有交集,因为我的
l
l
l是升序排列的,那么
b
r
e
a
k
break
break
对于
B
B
B,直接输出序列长度
这个可以直接用
s
e
t
set
set实现,时间复杂度
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
代码:
#include <iostream>
#include <cstdio>
#include <set>
#include <algorithm>
using namespace std;
struct Node {
int l, r;
friend bool operator < (Node aa, Node bb)
{
if (aa.r == bb.r) return aa.l < bb.l;
return aa.r < bb.r;
}
Node(){}
Node(int a, int b)
{
l = a, r = b;
}
};
char chr;
int AL, AR, num, n;
set <Node> dr;
int main()
{
scanf("%d", &n);
for (int k = 1; k <= n; k++)
{
scanf(" %c", &chr);
if (chr == 'A')
{
num = 0;
scanf("%d %d", &AL, &AR);
set <Node>::iterator pos = dr.lower_bound(Node(0, AL));
while (pos != dr.end())
{
Node cdp = *pos;
if (AR >= cdp.l) dr.erase(pos), num++; else break;
pos = dr.lower_bound(Node(0, AL));
}
dr.insert(Node(AL, AR));
printf("%d\n", num);
}
else {
num = dr.size();
printf("%d\n", num);
}
}
return 0;
}