zoukankan      html  css  js  c++  java
  • 洛谷P2342 叠积木

    题目背景

    (Cube Stacking, 2004 Open)

    题目描述

    约翰和贝西在叠积木。共有(30000)块积木,编号为(1)(30000)。一开始,这些积木放在地上,自然地分成(N)堆。贝西接受约翰的指示,把一些积木叠在另一些积木的上面。一旦两块积木相叠, 彼此就再也不会分开了,所以最后叠在一起的积木会越来越高。约翰让贝西依次执行(P)条操作,操作分为两种:

     第一种是移动操作,格式为“移动(X)(Y)的上面”。(X)(Y)代表两块积木的编号,意思是将X所的那堆积木,整体叠放到(Y)所在的那堆积木之上;

     第二种是统计操作,格式为“统计(Z)下方的积木数量”。(Z)代表一块积木的编号,意思是贝西需要报告在编号为(Z)的积木之下还有多少块积木

    请编写一个程序,帮助贝西回答每条统计问题。

    输入输出格式

    输入格式:

     第一行:单个整数:(P,1 ≤ P ≤ 10^5)

     第二行到第(P + 1)行:每行描述一条命令,如果这行开头的字母是 (M),代表一条移动命令,后面的两个整数代表上文中的X和(Y);如果开头字母是 (C),代表一条统计命令。后面的整数代表上文中的(Z),保证所有的移动命令都有意义,(X)(Y)不会已经出现在同一堆积木里

    输出格式:

     对每一个统计命令,输出正确回答,用换行符分开每个查询的结果

    输入输出样例

    输入样例#1:

    6
    M 1 6
    C 1
    M 2 4
    M 2 6
    C 3
    C 4
    

    输出样例#1:

    1
    0
    2
    

    说明

    第一次查询时, (1) 下面只有一个 (6);第二次查询时, (3) 下面没有任何积木;第三次查询时,(4) 下面有两块积木:(1)(6)

    思路:并查集的题目就是不一样,代码短小精悍,思路却很难想……对于这道题目来说,我们用一个(s)数组表示某个积木上方有多少个积木,再用一个数组(a)表示以某个点为顶的积木的个数,在并查集路径压缩的过程中让(s[x]+=s[fa[x]]),就是说(x)的父亲是在(x)上面的,那么就把它父亲上面的积木也加到(x)上面来,然后对于每个移动命令,是把以(x)为顶的那一块放到(y)上面,那么我们就更新(x)(y)的父亲,然后以(x)为顶的积木个数变成了原本以(x)为顶的积木个数加上原本以(y)为顶的积木个数,(y)上方的积木个数就加上了原本以(x)为顶的积木个数,然后对于每个统计命令,因为要求对于(x)输出(x)下面的积木的个数,那么就是以(x)为顶的积木个数减去(x)上面的积木个数再减(1)(因为(x)不在(x)的下方)。

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define maxn 30007
    using namespace std;
    int p,fa[maxn],s[maxn],a[maxn];
    string s1;
    inline int qread() {
      char c=getchar();int num=0,f=1;
      for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
      for(;isdigit(c);c=getchar()) num=num*10+c-'0';
      return num*f;
    }
    int find(int x) {
      if(fa[x]==x) return x;
      int res=find(fa[x]);
      s[x]+=s[fa[x]];
      return fa[x]=res;
    }
    int main() {
      p=qread();
      for(int i=1;i<=30000;++i) a[i]=1,fa[i]=i;
      for(int i=1,x,y;i<=p;++i) {
        cin>>s1;
        if(s1=="M") {
          x=qread(),y=qread();
          int zrj=find(x),cyh=find(y);
          if(zrj!=cyh) {
            fa[cyh]=zrj;
            s[cyh]+=a[zrj];
            a[zrj]+=a[cyh];
            a[cyh]=0;
          }
        }
        else {
          x=qread();
          int zrj=find(x);
          printf("%d
    ",a[zrj]-s[x]-1);
        }
      }
      return 0;
    }
    
  • 相关阅读:
    Linux中gdb 查看core堆栈信息
    爱因斯坦名言
    Symbian OS 源码下载方式
    Windows 2003+VS2005+SP1 “无法使用此产品的安装源,请确认安装源存在,并且您可以访问它”的错误
    Visual Studio 2012 Ultimate RTM 序列号
    STL容器erase的使用陷阱
    C++ 迭代器失效
    C++ 类的静态成员详细讲解[静态成员变量链接错误]
    Ubuntu 启动黑屏解决
    android中KSOAP2中的anytype{}问题
  • 原文地址:https://www.cnblogs.com/grcyh/p/10153942.html
Copyright © 2011-2022 走看看