有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
主要看操作2
开一个数组near[],near[i]=j表示从i往前,与i不同的第一个部门是j
然后i从y倒着枚举到x,i每次跳到near[i]
一、
优化1:读入优化
优化2:输出用puts
优化3:函数前+inline
加了这3个优化刚刚卡过去,2个点都900多ms了
#include<cstdio> #define N 200001 using namespace std; int n,m; int fa[N],near[N]; int type,x,y; inline int find(int i) {return fa[i]==i ? fa[i]:fa[i]=find(fa[i]);} inline int init() { int x=0;char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();} return x; } inline void unionn() { fa[find(x)]=find(y); }
inline void merge()
{
int t,i=y;
while(i>=x&&(t=near[i])>=x)
{
fa[find(t)]=fa[find(i)];
near[i]=near[t];
i=t;
}
}
int main() { n=init();m=init(); for(int i=1;i<=n;i++) { fa[i]=i;near[i]=i-1; } for(int i=1;i<=m;i++) { scanf("%d",&type); x=init();y=init(); if(type==1) unionn(); else if(type==2) merge(); else { int r1=find(x),r2=find(y); if(r1==r2) puts("YES "); else puts("NO "); } } }
二、
事实证明读入一个数字用读入优化也比scanf快
我真的只是把type的读入由scanf改成了也用读入优化
#include<cstdio> #define N 200001 using namespace std; int n,m; int fa[N],near[N]; int type,x,y; inline int find(int i) {return fa[i]==i ? fa[i]:fa[i]=find(fa[i]);} inline int init() { int x=0;char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();} return x; } inline void unionn() { fa[find(x)]=find(y); } inline void merge() { int t,i=y; while(i>=x&&(t=near[i])>=x) { fa[find(t)]=fa[find(i)]; near[i]=near[t]; i=t; } } int main() { n=init();m=init(); for(int i=1;i<=n;i++) { fa[i]=i;near[i]=i-1; } for(int i=1;i<=m;i++) { type=init();x=init();y=init(); if(type==1) unionn(); else if(type==2) merge(); else { if(find(x)==find(y)) puts("YES "); else puts("NO "); } } }