题目来源: 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; }