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;
}