1930: 帽子戲法
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 88 Solved: 24
[Submit][Status][Web Board]
Description
小A家有很多很多頂帽子初始時帽子都是獨立分開的,每頂帽子都有一個編號用於區分.小A會有以下操作之一:
1.將編號爲y的帽子所在的帽子堆放在編號爲x的帽子所在的帽子堆頂上,如果x,y在同一堆則不做任何動作.
2.小A會向你詢問編號爲x的帽子上方有多少隻帽子.
Input
輸入有多組數據:
第一行輸入N,M分別爲帽子數和操作數(1<=N<=40000,1<=M<=400000)
帽子的編號對應1,2,3...,N.
接下來有M行輸入爲 T x y 對應操作1. Q x 對應操作2.
Output
對於小A的詢問輸出位於編號爲x的帽子上方的帽子數.
Sample Input
2 2
T 1 2
Q 1
Sample Output
1
HINT
Source
【解題思路】
num[i]:每個帽子上的帽子數
pos[i]:每個帽子堆的帽子數,i 是這堆帽子的最上面的帽子編號
需要注意的是在每一次合併的時候是把兩個根節點合併,也就是說num數組只更新該點到根節點那條路徑上的值,但是根節點的其他兒子節點並沒有被更新,所以在查詢的時候,需要再用並查集遍歷一遍查詢節點的路徑上的num。
【代碼】
#include<bits/stdc++.h>
using namespace std;
const int maxn=4e5+5;
int pre[maxn],num[maxn],pos[maxn];
//num表示每個帽子上的帽子數 pos表示每個帽子堆的帽子數
int findroot(int x)
{
if(x!=pre[x])
{
int fx=pre[x];
pre[x]=findroot(pre[x]);
num[x]+=num[fx];
}
return pre[x];
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
for(int i=0;i<=n;i++)
{
pre[i]=i;
num[i]=0;
pos[i]=1;
}
while(m--)
{
char ch=getchar();
while(ch!='T'&&ch!='Q')ch=getchar();
if(ch=='T')
{
int x,y;
scanf("%d%d",&x,&y);
int fx=findroot(x),fy=findroot(y);
if(fx!=fy)
{
pre[fx]=fy;
num[fx]+=pos[fy];
pos[fy]+=pos[fx];
}
}
else
{
int x;
scanf("%d",&x);
findroot(x);
printf("%d\n",num[x]);
}
}
}
return 0;
}