HDU 2818 Building Block

Building Block

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 151 Accepted Submission(s): 67
 
Problem Description
John are playing with blocks. There are N blocks (1 <= N <= 30000) numbered 1...N。Initially, there are N piles, and each pile contains one block. Then John do some operations P times (1 <= P <= 1000000). There are two kinds of operation:

M X Y : Put the whole pile containing block X up to the pile containing Y. If X and Y are in the same pile, just ignore this command. 
C X : Count the number of blocks under block X 

You are request to find out the output for each C operation.
 
Input
The first line contains integer P. Then P lines follow, each of which contain an operation describe above.
 
Output
Output the count for each C operations in one line.
 
Sample Input
6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4
 
Sample Output
1
0
2
 
 
Source
题目大意:

移动小方块,  m  a  b   代表将  a  所在的所有小方块移动到  b 上面
Q  a  代表  查询  a 下面多少啊个 小方块。

思路:

带权并查集,用两个数组维护  num  和  down  
我的天哪,cout jur比 printf 慢好多。

AC代码:

#include <iostream>
#include<stdio.h>
using namespace std;
const int MAX = 300000;
int n,m,k;
int parent[MAX+10];
int num[MAX+10];
int down[MAX+10];
//total[GetParent(a)]是a所在的 group的人数
int GetParent(int a)
{
    //获取a的根,并把a的父节点改为根
    if( parent[a]!= a)
    {
        int t= GetParent(parent[a]);
        down[a]+=down[parent[a]];
        parent[a]=t;
    }
    return parent[a];
}
void Merge(int a,int b)
{
    int p1 = GetParent(a);
    int p2 = GetParent(b);
    if( p1 != p2 )
    {
        parent[p1] = p2;
        down[p1]=num[p2];
        num[p2]+=num[p1];
    }
}
int main()
{
    char ss[15];
    int h,s;
    while(~scanf("%d",&n))
    {
        for(int i = 0;i <=300000; ++i)
        {
            parent[i] = i;
            num[i]=1;
            down[i]=0;
        }
        for(int i=0;i<n;i++)
        {
            scanf("%s",&ss);
            if(ss[0]=='M')
            {
                scanf("%d",&h);
                scanf("%d",&s);
                Merge(h,s);
            }
            else
            {
                scanf("%d",&h);
                GetParent(h);
                printf("%d\n",down[h]);
            }
        }
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值