3294. Building Block
Time Limit: 1.0 Seconds
Memory Limit: 65536K
Total Runs: 840 Accepted Runs:235
John are playing with blocks. There are
N blocks (1 ≤
N ≤ 30000) numbered 0..
N-1. 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 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.
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
6M 1 6C 1M 2 4M 2 6C 3C 4
Sample Output
102
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;
}