Solution
给定
n
n
n个区间
[
l
,
r
]
[l, r]
[l,r], 你需要将他们放到不同的并查集里, 且满足: 只要两个区间是相交的 他们必须处在同一个并查集里!
.
另个角度说, 我们将这
n
n
n个区间当做是
n
n
n个点, 如果两个区间是相交的 就连接一条无向边, 最终, 求有多少个’连通图’;
注意我们要用 O ( n ) O(n) O(n)的时间, 虽然最多是有 O ( n 2 ) O(n^2) O(n2)条边, 但我们最终的目的 就是求有多少个连通图, 或者更精确的说 我们就是要将他们放到一个’并查集’里 (比如 n n n个点在同一个并查集 虽然有 n 2 n^2 n2条边, 但我们其实用 O ( n ) O(n) O(n)的时间 就可以将他们放到一个并查集里)
@Delimiter
对区间按照 l l l 从小到大排序, 然后使用双指针;
对于当前
i
i
i区间, 我们只关注 所有
>
i
> i
>i的区间 能与他相交的 (对于
<
i
<i
<i且与他相交的, 不在这里处理, 而是在
<
i
<i
<i那处理)
.
此时有一个性质, 令
r
>
i
r > i
r>i为第一个不相交的区间, 那么
[
i
+
1
,
.
.
.
,
r
)
[i+1,..., r)
[i+1,...,r)都与当前区间相交, 而
[
r
,
r
+
1
,
.
.
.
]
[r, r+1, ...]
[r,r+1,...]均不相交;
.
注意,
i
i
i 与
r
r
r不相交, 虽然
i
i
i与
i
+
1
i+1
i+1相交, 但是
i
+
1
i+1
i+1可能与
r
r
r相交; 总之就是双指针;
Code
pair< int, int> A[N];
sort( A, A + N);
DisjointSet S( N, N);
int r = 1;
for( int l = 0; l < N; ++l){
while( r < n && ( A[ r].first <= A[ l].second)){
S.Merge( l, r);
++ r;
}
}
`N - S.Get_mergedTimes()` = 并查集的个数;