描述
题解
典型的并查集问题,由于需要区间更新,所以这里要维护一个 pre[] 数组,表示当前记录点与在它前边且最靠近它的不同部门的点。
代码十分容易理解,就不再赘述了。
代码
#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 2e5 + 10;
int n, q;
int fat[MAXN];
int pre[MAXN];
int find(int x)
{
return x == fat[x] ? x : fat[x] = find(fat[x]);
}
void merge_1(int x, int y)
{
x = find(x);
y = find(y);
if (x != y)
{
fat[y] = x;
}
}
void merge_2(int x, int y)
{
for (int i = y, p; i >= x && pre[i] >= x; i = p)
{
p = pre[i];
fat[find(p)] = fat[find(i)];
pre[i] = pre[p];
}
}
template <class T>
inline void scan_d(T &ret)
{
char c;
ret = 0;
while ((c = getchar()) < '0' || c > '9');
while (c >= '0' && c <= '9')
{
ret = ret * 10 + (c - '0'), c = getchar();
}
}
void init()
{
for (int i = 1; i <= n; ++i)
{
fat[i] = i;
pre[i] = i - 1;
}
}
int main()
{
scan_d(n), scan_d(q);
init();
int t, x, y;
while (q--)
{
scan_d(t), scan_d(x), scan_d(y);
if (t == 1)
{
merge_1(x, y);
}
else if (t == 2)
{
merge_2(x, y);
}
else
{
if (find(x) == find(y))
{
puts("YES");
}
else
{
puts("NO");
}
}
}
return 0;
}