hdu2818與hdu3635 (帶權並查集)

2021-09-25 19:58:10 字數 3265 閱讀 6747

約翰正在玩積木。有n個block (1 <= n <= 30000)編號為1…n .最初有n根樁,每根樁包含乙個塊。然後john做一些運算p次(1 <= p <= 1000000)。有兩種操作:

m x y:把包含x塊的整個堆放到包含y塊的堆上,如果x和y在同一堆上,就忽略這個命令。

c x計算方塊x下的方塊數

要求您找出每個c操作的輸出。

輸入第一行包含整數p,然後是p行,每一行包含上面描述的操作。

輸出在一行中輸出每個c操作的計數。

sample input

6m 1 6

c 1m 2 4

m 2 6

c 3c 4

sample output10

2分析:

用d[i]表示i下方的石子個數

用num[i]表示i集合中總石子個數

pre[i]表示集合中 i 的父節點

這題有點不一樣,根節點應該是最底下的石子(是我思維定式了)。

1.合併操作

因為題目是把x堆放到y堆上,所以y應該是新根,所以pre[x]=y

同時x下方的石子數量增多,因此d[x]+=num[y]

集合總石子數增多,因此num[y]+=num[x]

那麼問題來了,d[x]+=num[y]操作只更新了x乙個石子,x上方的石子數量沒有更新啊?

這點可以在並查集查根的過程中操作(類似線段樹的lazy操作,等到查詢的時候再更新)

因此:2.查詢操作

如果當前節點x的根為自己本身(pre[x]==x),毫無疑問直接return x

如果當前節點不是根節點:

從操作1可知,我們在原來的根節點x處做了d[x]=num[y]

原先的x集合中每乙個元素的d都應該加上num[y]

我們知道當乙個節點為根節點的時候,d[i]=0,

因此d[x]的值就是原來x集合中每個元素應該加上的值(這時候d[x]=num[y])

一步一步解析:

//假設根為y

intffind

(int a)

else

}

code:
#include

#include

#include

#include

#include

#include

#define set0(a) memset(a,0,sizeof(a))

#define set1(a) memset(a,-1,sizeof(a))

#define setinf(a) memset(a,0x3f3f3f3f,sizeof(a))

#define ll long long

#define p pair

#define mp(a,b) make_pair(a,b)

const

int inf=

0x3f3f3f3f

;const

int inn=

0x80808080

;using

namespace std;

const

int maxm=

5e4+5;

int pre[maxm]

;//pre[i]表示i的下面一層

int d[maxm]

;//d[i]表示i下面的石塊總數(不包括本身)

int num[maxm]

;//num[i]表示i所在堆的石塊總數

void

init()

}int

ffind

(int x)

else

}int

main()

}else

}return0;

}

五百年後,龍珠的數量將會出乎意料地增加,所以對孫悟空來說把所有的龍珠聚集在一起太難了。

他的國家有n個城市,而世界上正好有n個龍珠。首先,為了第i個龍珠,神聖的龍會把它放在第i個城市。經過漫長的歲月,一些城市的龍珠會被運送到其他城市。為了節省體力,悟空計畫乘飛天雲,一種神奇的飛天雲來收集龍珠。

每次悟空收集乙個龍珠的資訊,他都會問你那個龍珠的資訊。你必須告訴他球在哪個城市,在那個城市有多少個龍珠,你還需要告訴他球已經被運送了多少次。

輸入輸入的第一行是乙個正整數t(0 < t <= 100)。

對於每種情況,第一行包含兩個整數:n和q (2 < n <= 10000, 2 < q <= 10000)。

下列q行每一行都包含乙個事實或乙個問題,格式如下:

所有和a在同乙個城市的龍珠都被運到了b球所在的城市。你可以假設這兩個城市是不同的。

問:悟空想知道x (ath球所在城市的id), y(第x個城市的球數),z (ath球的轉運時間)。(1 <= a, b <= n)

輸出對於每個測試用例,輸出作為示例輸出形式的測試用例號。然後,對於每個查詢,輸出一行三個由空格分隔的整數x y z。

分析:類似上一題

cnt陣列存轉移次數,

num記錄集合中龍珠的數量

合併和查詢更新都和上一題基本一致

code:

#include

#include

#include

#include

#include

#include

#define set0(a) memset(a,0,sizeof(a))

#define set1(a) memset(a,-1,sizeof(a))

#define setinf(a) memset(a,0x3f3f3f3f,sizeof(a))

#define ll long long

#define p pair

#define mp(a,b) make_pair(a,b)

const

int inf=

0x3f3f3f3f

;const

int inn=

0x80808080

;using

namespace std;

const

int maxm=

1e4+5;

int pre[maxm]

;int num[maxm]

;int cnt[maxm]

;void

init

(int n)

}int

ffind

(int x)

else

}int

main()

}else}}

return0;

}

hdu3635之並查集

include include include include include include include include include include define inf 99999999 using namespace std const int max 10000 10 father ...

HDU 2818 向量並查集

題目鏈結 題目大意 每次指定一塊磚頭,移動磚頭所在堆到另一堆。查詢指定磚頭下面有幾塊磚頭。解題思路 hdu資料有問題 資料從0開始,且給定n塊磚頭 比如1000 資料會有第1005塊磚頭,導致訪問越界。解決方案 並查集初始化範圍改為0 maxn 30005 由於只給定一塊磚頭,卻要移動所在堆。所以需...

hdu5967 小R與手機

用lct,不要mak eroo tmakeroot makero ot一棵樹的根節點可能是真的根節點 a root 0 a root 0 a roo t 0 也可能這個根節點還指向樹里的另乙個節點 這種情況下a r oot 0a root not0 a root 0 更改指向的時候,先切斷原來的邊,...