Zexal的拯救世界
題目
知識點:並查集
在一條數軸上坐落着N個國家,分別是1~N。一開始所有的國家都處於黑暗狀態。接着Zexal使用M次魔法,第i次魔法將會爲[Li,Ri]這些國家帶來光明。請輸出每次魔法使用後仍然處於黑暗狀態下的國家數量。
輸入
輸入一行爲N和M。下面M行每行兩個數Li、Ri (1<=Li<=Ri<=N<=200000,1<=M<=200000)
輸出
輸出M行,每次魔法使用後仍然處於黑暗狀態下的國家數量。
輸入樣例
10 3
3 3
5 7
2 8
輸出樣例
9
6
3
思路
知識點:並查集
在一條數軸上坐落着N個國家,分別是I~N。一開始所有的國家都處於黑暗狀態。接着Zexal使用M次魔法,第i次魔法將會爲[Li,Ri]這些國家帶來光明。請輸出每次魔法使用後仍然處於黑暗狀態下的國家數量。
運用並查集(指向數組),指向當前國家右邊第一個處於黑暗的國家, 如果全部國家都處於光明瞭就指向 n+1。
這樣的話,每個國家就不會被重複計算,所以 O(n+m)可以 輕鬆水過。
Mogg:線段樹裸題。
但其實並查集也能做,每次覆蓋一個區間後,使區間內每一個點都指向最右邊的已經被覆蓋的點,這樣重複覆蓋的時候就可以很快跳過。均攤複雜度很低。
代碼
#include <cstdlib>
#include <iostream>
using namespace std;
typedef long long ll;
const int ms = 200020;
int pre[ms], vis[ms];
int find(int x)
{
if (pre[x] != x)
pre[x] = find(pre[x]);
return pre[x];
}
void join(int x, int y)
{
int fx = find(x), fy = find(y);
if (fx != fy)
{
pre[fx] = fy;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, k, a, b, res = 0;
cin >> n >> k;
for (int i = 1; i <= n; ++i)
pre[i] = i;
res = n;
for (int i = 0; i < k; ++i)
{
cin >> a >> b;
for (int j = a; j <= b; j++)
{
if (vis[j]) j = find(j);
else vis[j] = 1, res--;
join(j, b);
}
cout << res << "\n";
}
return 0;
}