線段樹合併 HNOI2012 永無鄉

2022-03-27 09:32:40 字數 2086 閱讀 2471

問題 b: [hnoi2012]永無鄉

時間限制: 1 sec 記憶體限制: 128 mb

提交: 50 解決: 28

[提交][狀態][討論版]

題目描述

永無鄉包含 n 座島,編號從 1 到 n,每座島都有自己的獨一無二的重要度,按照重要度可 以將這 n 座島排名,名次用 1 到 n 來表示。某些島之間由巨大的橋連線,通過橋可以從乙個島 到達另乙個島。如果從島 a 出發經過若干座(含 0 座)橋可以到達島 b,則稱島 a 和島 b 是連 通的。現在有兩種操作:b x y 表示在島 x 與島 y 之間修建一座新橋。q x k 表示詢問當前與島 x連通的所有島中第 k 重要的是哪座島,即所有與島 x 連通的島中重要度排名第 k 小的島是哪 座,請你輸出那個島的編號。

輸入 輸入檔案第一行是用空格隔開的兩個正整數 n 和 m,分別 表示島的個數以及一開始存在的橋數。接下來的一行是用空格隔開的 n 個數,依次描述從島 1 到島 n 的重要度排名。隨後的 m 行每行是用空格隔開的兩個正整數 ai 和 bi,表示一開始就存 在一座連線島 ai 和島 bi 的橋。後面剩下的部分描述操作,該部分的第一行是乙個正整數 q, 表示一共有 q 個操作,接下來的 q 行依次描述每個操作,操作的格式如上所述,以大寫字母 q 或b 開始,後面跟兩個不超過 n 的正整數,字母與數字以及兩個數字之間用空格隔開。 對於 20%的資料 n≤1000,q≤1000

對於 100%的資料 n≤100000,m≤n,q≤300000

輸出 對於每個 q x k 操作都要依次輸出一行,其中包含乙個整數,表 示所詢問島嶼的編號。如果該島嶼不存在,則輸出-1。

樣例輸入

5 1

4 3 2 5 1

1 2

7 q 3 2

q 2 1

b 2 3

b 1 5

q 2 1

q 2 4

q 2 3

樣例輸出

-1 2

5 1

2 提示

這只是第一篇,還有一篇關於無旋treap啟發式搜尋的題解。

----------
得更新一下自己的知識了,線段樹合併。

子節點不再是x*2….了,必須動態開點,因為最開始有多棵線段樹,平常的修改並無多大區別。每棵樹的範圍都是1~n,樹的合併,只不過是把各葉子結點的值累積起來,合併在一起。

那麼對於子樹合併,就可以把問題改為合併左右子樹了。遞迴到葉子即可。

----------
那麼對於這道題,用並查集維護每乙個聯通塊,以優先順序為下標建權值線段樹,維護區間有多少個點(優先順序不相重複,故每個葉子最多乙個)。而最後查詢類似平衡樹,若左子樹的sum>=rank,只找左子樹;否則,rank-sum後找右子樹。

#include

#include

#include

#include

#include

#define n 100005

using namespace std;

int n,m,sz,q,f[n],sum[n],id[n],root[n];

intlc[n*18],rc[n*18],h[n*18];

int find(int

x)void add(int &x,int l,int r,int k)

int mid=(l+r)/2;

if(k<=mid)add(lc[x],l,mid,k);

else add(rc[x],mid+1,r,k);

h[x]=h[rc[x]]+h[lc[x]];

}int hb(int

x,int

y)int

q(int x,int l,int r,int k)

int main()

for(int i=1;i<=n;i++)

scanf("%d",&q);char s[2];

while(q--)

int k=q(root[fx],1,n,y);

printf("%d\n",id[k]);

}else}}

}

HNOI2012 永無鄉 線段樹合併 並查集

傳送門 其實很裸,用並查集維護每個點的資訊已經別合併到哪個線段樹裡面了,然後權值線段樹查第k大就行。我一開始和 地沒用並查集,然後發現rt沒有傳遞性。寫著寫著反應過來,其實一開始也可以這麼寫,用rt當並查集用就行,我感覺更 了。includeusing namespace std define in...

HNOI2012 永無鄉 splay合併

題目描述 永無鄉包含 n 座島,編號從 1 到 n 每座島都有自己的獨一無二的重要度,按照重要度可以將這 n 座島排名,名次用 1 到 n 來表示。某些島之間由巨大的橋連線,通過橋可以從乙個島到達另乙個島。如果從島 a 出發經過若干座 含 0 座 橋可以 到達島 b 則稱島 a 和島 b 是連通的。...

HNOI2012 永無鄉 題解

對於每乙個點先建立乙個權值線段樹,之後並查集維護 更改連通性。不知道權值線段樹是啥的戳我 聯通就直接把祖先連起來然後合併線段樹 include include using namespace std const int n 100005 int size n 20 n,m,fa n type,q,r...