POJ 1988 Cube stacking

有N(N<=30,000)堆方块,开始每堆都是一个方块。方块编号1 – N. 有两种操作:
M x y : 表示把方块x所在的堆,拿起来叠放到y所在的堆上。
C x : 问方块x下面有多少个方块。
操作最多有 P (P<=100,000)次。对每次C操作,输出结果。
 

Input

* Line 1: A single integer, P 

* Lines 2..P+1: Each of these lines describes a legal operation. Line 2 describes the first operation, etc. Each line begins with a 'M' for a move operation or a 'C' for a count operation. For move operations, the line also contains two integers: X and Y.For count operations, the line also contains a single integer: X. 

Note that the value for N does not appear in the input file. No move operation will request a move a stack onto itself. 

Output

Print the output from each of the count operations in the same order as the input file. 

Sample Input

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

Sample Output

1
0
2

under[i]是指i的下面有多少方块,当两堆方块合并时,如,merge(a,b)将b堆根放在a堆根的下面,此时需要改变b堆的under值,他的值等于他的根的under值也就是a的under值加上他本身的under值。

在状态压缩过程中,也需要改变under的值,对于每一个结点,他们的under 值等于本身的under值加上他们的父节点的under的值

 

 

 

 

 

#include<iostream>
#include<cstdio>
#define n1 31000
using namespace std;
int pre[n1],under[n1];
int total[n1];
int n;
int p;
int getboot(int x){
    if(x!=pre[x]){
        int t=getboot(pre[x]);
        under[x]+=under[pre[x]];
        pre[x]=t;
        return pre[x];
    }
    return x;
}
void Merge(int a,int b){
    int pb=getboot(b);
    int pa=getboot(a);
    if(pb==pa)
    return;
    pre[pb]=pa;
    under[pb]=total[pa];//堆方块时,pb连接到pa上,此时pb的下面全是a的方块,如图1
    total[pa]+=total[pb];
}
int main(){
    for(int i=0;i<n1;i++){
            under[i]=0;
            pre[i]=i;
            total[i]=1;
    }
    scanf("%d",&p);
    for(int i=0;i<p;i++)
	{
		char s[20];
		int a,b;
		scanf("%s",s);
		if(s[0]=='M')
		{
			scanf("%d%d",&a,&b);
			Merge(b,a);
		}
		else
		{
			scanf("%d",&a);
			getboot(a);
			printf("%d\n",under[a]);
		}
	}
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值