P2342 叠积木

P2342 叠积木

    • 17通过
    • 66提交
  • 题目提供者wwqk4444
  • 标签树状数组线段树USACO
  • 难度普及+/提高

提交该题 讨论 题解 记录

最新讨论

  • 暂时没有讨论

题目背景

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

AC代码+题解:

/*
题解:
正确性解释:以底层元素为并查集的代表元素,保证cnt[]更新到底端的时候不会多加,因为cnt[fa[x]]必为0 
fa[x]=y; 表示x的父亲是y;          (初始化是自身)
top[x]=t;表示x上面的代表编号是t;  (初始化是自身)
cnt[x]=t;表示x以下木块的数量是t;  (初始化是0)
find()更新时,两堆合并时,利用回溯,更新top[x]=top[t];cnt[x]=cnt[t]+cnt[x];(画图易知) 
ps:每次合并或查询,都要find()一次,要不然会WA。  
*/
#include<cstdio>
#include<iostream>
using namespace std;
#define N 30010
int fa[N],cnt[N],top[N];
inline int read(){
    register int x=0,f=1;
    register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline char in(){
    for(register char ch=getchar();;ch=getchar()) if(ch>='A'&&ch<='Z') return ch;
}
int find(int x){
    if(fa[x]==x)return x;
    int t=fa[x];
    fa[x]=find(fa[x]);
    fa[x]=fa[t];
    top[x]=top[t];
    cnt[x]=cnt[t]+cnt[x];
    return fa[x];
}
int main(){
    int n,x,y,a,b;char ch;
    n=read();
    for(int i=1;i<=30000;i++) fa[i]=top[i]=i;
    for(int i=1;i<=n;i++){
        if((ch=in())=='M'){
            a=read();b=read();
            x=find(a),y=find(b);
            fa[x]=y;find(top[y]);
            cnt[x]=cnt[top[y]]+1;
            top[y]=top[x];
        }
        else{
            x=read();find(x);
            printf("%d
",cnt[x]);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shenben/p/5757004.html