洛谷 1196 題解

2021-09-19 16:56:48 字數 2220 閱讀 7339

有30000

30000

3000

0個佇列,初始每個佇列裡有元素1,2

,3

⋯30000

1,2,3\cdots 30000

1,2,3⋯

3000

0。兩種指令:

1.m mmi

iij

jj 編號為i

ii的佇列整個接到jjj上

2.c cci

iij

jj 問編號為i

ii,j

jj的兩個點之間(不包含i

ii,j

jj)有多少點。(如果不在乙個佇列裡輸出−1-1

−1)輸入

4m 2 3

c 1 2

m 2 4

c 4 2

輸出-1

1這個題目是我在體育課上完成的思路,回來寫的**。。。

趁著剛做完,講講我思考的過程。

剛看到這個題的時候,第乙個想到的肯定是並查集。但是突然注意到詢問是要求中間有多少點,一臉懵逼:這怎麼維護?難道是上splay??(珂是splay我不會啊。。。)

慢慢分析這個題,我們肯定不能暴力維護點的位置。想想那些區間求和的問題,都怎麼做的:沒錯,字首和

\color字首和

字首和!我們用sum

[i

]sum[i]

sum[i]

表示i

ii這個點在i

ii的佇列中前面(不包括i

ii)有多少點。在詢問的時候,只要將兩個sum

sumsu

m值取絕對值相減,然後±

1\pm1

±1或者不變就珂以得到了。究竟是哪個呢?經過對樣例的模擬,我們會發現此時應該是−1-1

−1才是正確的。

上面這個看起來很好理解。那麼如果我們要合併兩個佇列的時候,比方說是x

xx佇列和y

yy佇列,那麼x

xx佇列的每個元素的sum

sumsu

m都因為接在了y

yy佇列的後面,所以每個都要+=c

nt[y

]+=cnt[y]

+=cnt[

y],其中cnt

[y

]cnt[y]

cnt[y]

表示y

yy佇列的元素個數。由於我們需要修改所有x

xx佇列中的元素,遍歷就不珂避免了,一次合併操作就要o(n

)o(n)

o(n)

了。怎麼優化這個呢?

我們想想我們在搞並查集問題的時候都是怎麼搞的:乙個祖先一一對應乙個集合。乙個集合中所有的記錄工作都交給祖

先來完成

\color交給祖先來完成

交給祖先來完

成。所以我們考慮這樣做:只對祖先的sum

sumsu

m加值,在查詢點i

ii的時候逐個加上父親(不包括祖先)的sum

sumsu

m值,就是點i

ii實際的sum

sumsu

m值。然後發現查詢就o(n

)o(n)

o(n)

了,因為我們如果進行路徑壓縮,資訊就丟失了。而實際上,我們珂以在路徑壓

縮的時候

就更新i

點的su

m\color路徑壓縮的時候就更新i點的sum

路徑壓縮的時

候就更新

i點的s

um值,然後讓i

ii就算直接接到祖先上,也不會丟失資料,就保證了資訊的正確性。這很好辦,只要在路徑壓縮回溯的路上順便加上這個值即可。

這樣一次操作就o(1

)o(1)

o(1)

了!!!

**:

#include

#define n 1001000

using

namespace std;

class

dsu}

intfind

(int x)

//找到x的祖先,並將x的sum值設定成所有父親(當然,不包括祖先)

void

merge

(int x,

int y)

//佇列x接到佇列y

}d;void

query()

else

else

//在乙個佇列裡}}

}main()

洛谷 1196 銀河英雄傳說

傳送門 寫題一時wa了時間不多了計畫還沒完成先放下去寫道水題好像是正確的選擇。對每個點記錄它到當前代表元的距離,初始都為0 到自己 合併時之前代表元的距離就等於它要合併的那個集合的size。路徑壓縮時先加上父親到代表元的距離,再把父親換成代表元。twenty include include incl...

洛谷 比賽題解

這套題的題目質量很高,寫一發題解。t1 cjwssb最近在物理學科上遇到了難題,他不會計算乙個電路中的總電阻,現在他找到了你,希望你能幫助他。這個電路有如下限定 1 電路只由導線以及電阻為一歐的電阻組成 2 保證電路從左到右連線,即每個電阻或導線的兩個連線點xy保證x 我們可以用dfs求解,這個電路...

洛谷1087題解

problem description 我們可以把由 0 和 1 組成的字串分為三類 全 0 串稱為b串,全 1 串稱為i串,即含有 0 又含有 1 的串則稱為f串。fbi樹是一種二叉樹,它的結點型別也包括f結點 b結點和i結點三種。由乙個長度為2 n的 01 串s可以構造出一棵fbi樹t,遞迴的構...