2019E0_D Zexal的拯救世界

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章