ACM模版

描述

题解

典型的并查集问题,由于需要区间更新,所以这里要维护一个 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;
}