zoukankan      html  css  js  c++  java
  • 重组公司

     
    题目来源: 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
    ");
            }
        }    
    } 
    
    
    
     
  • 相关阅读:
    WebForms 开发基础
    Web 开发基础
    Winform MDI窗体容器、权限、简单通讯
    Winform TextBox中只能输入数字的几种常用方法(C#)
    WinForm TreeView递归加载
    窗体四边阴影
    winform 进程,线程
    树状数组 / 二维树状数组
    zkw线段树
    [HNOI2014]世界树
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6368548.html
Copyright © 2011-2022 走看看