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