51nod 1525 重组公司

题目来源: CodeForces
基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题

有n个人在公司里面工作。员工从1到n编号。每一个人属于一个部门。刚开始每一个人在自己的部门负责自己的项目,这样的话公司里面就有n个部门。

然而,公司内部出现了危机,需要合并一些部门,以提高工作效率。team(person) 表示person这个人所在的部门。有以下两种合并操作:

1.    合并 team(x) 和 team(y)。 x和 y (1≤x,y≤n)是员工编号。如果team(x) 和 team(y)是同一个部门,那么就不操作。

2.    合并team(x),team(x+1),...,team(y),x 和 y (1≤x≤y≤n)是员工编号。

有一些查询操作,查询员工x 和 y (1≤x,y≤n)是否属于同一部门。

Input
单组测试数据。
第一行有两个整数n 和 q (1≤n≤200000, 1≤q≤500000)表示员工的数目和操作数目。
接下来q行,每行的格式是type x y。type∈{1,2,3}。如果type=1 或者 type=2,那么表示第一种或者第二种合并操作。如果type=3,表示查询员工x和y是否属于同一部门。
Output
对于第三种查询,如果属于同一部门输出YES,否则输出NO。
Input示例
样例输入1
8 6
3 2 5
1 2 5
3 2 5
2 4 7
2 1 2
3 1 7
Output示例
样例输出1
NO
YES
YES
 
 
  并查集 
  pre数组记录的是前面第一个与他是不是同个部门的点。
  因为记录的是前面一个 所以2操作要倒过来合并
  找题的时候突然看到这题没做完,
  然后发现 原来离A掉这个题 只差一个读入优化
#include <cstdio>
#include <cctype>
#define N 205000
int n,q,fa[N],pre[N];
int find_(int x) {return x==fa[x]?x:fa[x]=find_(fa[x]);}
template<typename T>
inline void read(T &x)
{
    register char ch=getchar();
    for(x=0;!isdigit(ch);ch=getchar());
    for(;isdigit(ch);x=x*10+ch-'0',ch=getchar());
}
int main()
{
    read(n);
    read(q);
    for(int i=1;i<=n;++i) fa[i]=i,pre[i]=i-1;
    for(int opt,x,y;q--;)
    {
        read(opt);
        read(x);
        read(y);
        if(opt==1) fa[find_(y)]=find_(x);
        else if(opt==2)
        {
            int end,i=y;
            for(;i>=x&&(end=pre[i])>=x;i=end)
            {
                fa[find_(end)]=fa[find_(i)];
                pre[i]=pre[end];
            }
        }
        else
        {
            if(find_(x)==find_(y)) puts("YES");
            else puts("NO");
        }
    }
    return 0;
}
 
 
原文地址:https://www.cnblogs.com/ruojisun/p/7648036.html