M X Y : Put the whole pile containing block X up to the pile containingY. IfX 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.
6 M 1 6 C 1 M 2 4 M 2 6 C 3 C 4
1 0 2
Author:SUN, Chao
Source:Multi-School Training Contest - TOJ Site #1
题意: 有N个木块,放在N个平台上,M x,y移动有x的平台,全部放到y的平台上
c x 输出x木块下有几个木块
一道并查集的题;
但是由于思考的不够细,一直wa,,再加上不懂c读取字符,导致了几次re。 一次ce
连水题都被难倒了,,贴一下。。。纪念又一个悲剧
设置三个数字: up [x] x上有几个木块
down[x] 下有几个木块
pre[x]是下面的一个木块是几号
//一堆木块,除了最底下的父亲是自己外,其他的木块父亲最终指向最底下
#include<cstdio>
using namespace std;
const int maxn = 30005;
int up[maxn];//记录木块上面的木块个数
int down[maxn];//记录木块下面的木块个数
int pre[maxn];//记录父亲结点
int stack[maxn];//堆栈
int sp = 0;
int find_pre(int root){//查找根
int u = root;
sp = 0;
while(pre[root] != root)//找根,且把链上的结点都加入栈
{
stack[sp++] = root;
root = pre[root];
}
for(int i = sp - 2 ;i > -1; i--)//更新链上的每个结点
{// -2 的原因是如果他的父亲是最底下的木块,就不用更新了。因为在 合并的时候更新过 1.0处
down[stack[i]] += down[stack[i+1]];
pre[stack[i]] = root;
}
return root;
}
int main()
{
int N,x,y;
char a;
while(scanf("%d",&N) != EOF)
{
for(int i = 0; i <= maxn; i++)
{
pre[i] = i;
up[i] = 0;
down[i] = 0;
}
for(int i = 0;i < N; i++)
{
getchar();
a = getchar();//读取字符
if(a == 'M')
{
scanf("%d%d",&x,&y); //1.0,更新点
int fx = find_pre(x);//找x的根
int fy = find_pre(y);//找y的根
if(fx == fy) continue;
down[fx] += up[fy] + 1;//更新结点信息
up[fy] += up[fx] + 1;
pre[fx] = fy;
}
else
{
scanf("%d",&x);
find_pre(x);
printf("%d\n",down[x]);
}
}
}
return 0;
}