重组公司

 
题目来源: 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
主要看操作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
");
        }
    }    
} 


 
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6368548.html