Problem
切割長方形蛋糕,使得每一塊上恰好有一個莓果,每一次切割的花費即線長,求最小花費。
Sample Input
|
|
Sample Output
|
|
Solution
利用 DP 精神,考慮每一個地方都去切割,定義 dp[x][y][w][h]
為左上角座標 (x, y),其長寬 (w, h)
的長方形蛋糕的最小花費。
沒有辦法對於連續空白之間只取一次切割,如果只切一次縱切的,切著左右兩側的橫切個數將會影響很大,所以每個位置都要嘗試。
|
|
切割長方形蛋糕,使得每一塊上恰好有一個莓果,每一次切割的花費即線長,求最小花費。
|
|
|
|
利用 DP 精神,考慮每一個地方都去切割,定義 dp[x][y][w][h]
為左上角座標 (x, y),其長寬 (w, h)
的長方形蛋糕的最小花費。
沒有辦法對於連續空白之間只取一次切割,如果只切一次縱切的,切著左右兩側的橫切個數將會影響很大,所以每個位置都要嘗試。
|
|
參照 Zerojudge d526: Binary Search Tree (BST) 按照插入的順序,建造一棵二元搜尋樹,原則上很簡單,但是很容易遇到極端的偏斜情況,如果插入順序很接近已經排序過的順序,則複雜度最慘為 O(n^2)
。
|
|
|
|
先稍微認識一下笛卡爾樹 (一種二元樹),每個節點為 <key, value>
,只看 key 時,笛卡爾樹是一棵二元搜尋樹,而看 value 時,它是一個最大堆 (或者是最小堆)。
在建造前,先撇清一點,笛卡爾樹的深度可能到達 n,與一般平衡樹不同。
笛卡爾樹如何建造 ? 假使已經對於 key 值由小到大排序 (升排序),那麼將點依序插入笛卡爾樹,能保證的是-由於要符合二元搜尋樹,新加入的點一定是這棵樹某個節點的右節點。知道這一點後,再往前考慮前一次插 入的點(它原本也符合再某節點的右節點),往這個節點往上爬,直到符合最大堆(性質 node.v > new_insert.v),這時將這個節點的右子樹移到新加入節點的左子樹 (此時符合二元搜尋樹的性質,也保有原本堆的性質)。就這麼持續入點下去。
這麼發現,往上爬的次數不超過節點個數,因為每個節點只會從右子樹換到左子樹。均攤下 O(n) (每個節點只會從右子樹推到左子樹一次,因此最多 n 次)
我們接著將 “按照順序插入的 BST” 轉換成建造笛卡爾樹,key 值依舊為輸入的元素大小,而 value 則訂為輸入順序,根據 key 值為一個二元搜尋樹,根據 value 建造一個最小堆,那麼仔細思考可以得到與原本相同的二元搜尋樹。
建造笛卡爾樹只需要花 O(n) 時間,但建造前必須根據 key 排序 O(n log n),所以複雜度為 O(n log n)。
在這樣的方式建造有一個缺點,並不知道途中插入的情況,只會在最後得到一樣的二元搜尋樹。假使要得到途中插入的情況,考慮離線處理,將所有操作儲存起來,而二元樹的節點位置並不會更動的情況下,事先建造一個靜態樹,隨後使用一個懶標記存在與否即可。
<key, value> = <i, A[i]>
所建造的笛卡爾樹,可以利用 LCA 的 tarjan 算法(離線作法) 在 O(n) 時間內完成。RMQ 假使查找 [l, r]
的最小值,又因為我們根據 value 建造最小堆,則根據 tarjan 的搜索順序,拜訪右子樹時(對於區間的 r 來說),左子樹將會跟其 LCA 合併,而 LCA 的 index 肯定比左子樹來得大 (大於等於 l),又根據最小堆保證是大於等於 l 且小於等於 r 的最小值。
|
|
給一棵樹
|
|
|
|
由於顏色不大於 10,可以安妥建造 10 棵線段樹,利用樹鏈剖分的概念,重邊將會取子樹最大的那一邊,其他都是輕邊,隨後保證每一個點往上爬升,最多經過 log n 個輕邊。
因此時間複雜度調整 O(log n)
詢問 O(log^2 n)
。
對於樹鏈剖分找 LCA 操作,針對兩個 (x, y) 所在的 node 而言,查看哪個 node 位置高低,調整到同高進行操作,保證爬的次數最多 log n,對於每一個 node 中建造一個線段樹,因此各自 query 也要 log n。
|
|
是否存在 weak link,使得兩個 component 會因為 weak link 斷掉而無法連通。
|
|
|
|
找橋 bridge!利用 back edge 的深度進行判斷。
|
|
問是否計算順序會影響結果,給一個有向圖,請問是否每一個操作都會 reduce 到同一個項目。
|
|
|
|
如果裡面有環肯定是不行的,因此需要偵測環是否存在。
在這之後,必須檢查是否會 reduce 到同一個項目,因此我們將每個 node reduce 的結果保存,之後取聯集,如果發現 reduce 項目超過一個則直接回傳失敗。
|
|
紅圓茵可最近隱居在板擦山研究魔法師的夢想,傳說中的魔法-「召喚蘿莉」。
只要成功練就這個魔法,茵可就可以召喚出一堆蘿莉,然後跟一堆蘿莉一起……嘿嘿嘿…..
目前茵可已經研究出N種可能可以成功魔法陣,接下來就是要測試這些魔法陣能不能成功召喚蘿莉,因為數量實在太多了,所以他決定先測試其中K種。為了測試魔法陣,茵可需要先開一個異次元空間,並且在裡面做測試(因為召喚蘿莉是個極大的魔法,發動時可能會造成空間扭曲,不小心毀掉可茵城就不好了。)。魔法陣都是圓形的,半徑為r,發動一個魔法陣需要以魔法陣為底高度為h的圓柱體空間。而茵可只能開出長方體的異次元空間,一個異次元空間有其長、寬、高,而魔法陣只能放置在該空間的地板上(長 x 寬那一面),所以要發動一個半徑為r,高度為h的魔法陣,茵可需要開一個長2r寬2r高h的異次元空間(體積2r x 2r x h)。現在茵可想要開一個異次元空間,而這個空間至少要能發動K個魔法陣(不必同時發動),這個空間的體積至少是多少。
第一行有兩個正整數 N,K(K<=N)
接下來N行每行有兩個正整數r,h代表一個魔法陣的半徑及發動需要高度(r,h<=100)
測資
輸出要發動其中K個魔法陣所需最小的異次元空間的體積是多少
|
|
|
|
範測所需體積為 224=16
可發動第1、2、5個魔法陣
這一題有兩種做法,直接窮舉 O(100 * 100)
的針對 [r, h]
找到 [0, r] x [0, h]
的數量是否大於 K,那麼可以在線性時間內完成。
而下面的做法,算是多此一步,原本想說能不能用 O(n log n)
時間內完成,但是會缺少部分調整資訊,也就是單純排序,以掃描線的基準會漏到資訊。
如果這一題的 r, h 很大的話,窮舉還是會耗費 O(n^2 log n)
,套用當前最佳解剪枝應該快上很多。
|
|
「哇!我終於解出來啦!咦?茵可呢?」剛解完K大數字差的你,在茵可家到處尋找,卻始終不見紅圓茵可的身影。
四處打聽之下,得知茵可前往神秘之山-「板擦山」修練神秘的魔法去了。板擦山本身有天然的結界,只有法力高強的魔法師才有辦法進入山中。「這下子我該怎麼找到茵可呢?」你苦思著,「想找茵可嗎?我可以告訴你怎麼找到茵可!」似乎是剛好路過的長頸鹿這麼說道。
板擦山的山腳下有好幾間便利商店,這些便利商店剛好開在結界外,茵可每天都會到山下的其中一間購買民生用品,而且到哪家便利商店是可以預測的。板擦山上有N個點,每個點有各自的編號,越高的點編號越小,點跟點之間有道路連接,茵可所在的山頂為編號0的點,便利商店也是其中的一個點。茵可每天會由山頂出發,經過一些點後到山下的便利商店買東西。當茵可走到一個點x後,他會先走跟x有連接的點中,編號比x大(當然要往山下走阿)的點中,編號最小的那一個。而下一次又到x時就走第二小的,直到編號比x大的點都走過一次,就會回到最小的點繼續走。(假設 3號點連到 1,4,5,第一次到3時,茵可會走向4。下一次到3時,茵可會走向5。再下一次到3時,茵可會走向4。)若一個點沒有連到編號比它大的點,則該點為便利商店。
你從長頸鹿手中的到了板擦山的地圖,你就可以預測茵可在第K天時會走到哪一家便利商店了!
第一行有兩個正整數N,M,K,表示有N個點(編號0~N-1)、M條邊(M<=N*(N-1)/2)及詢問第K天茵可會到哪個點。
接下來M行每行有兩個整數a,b表示a跟b間有一條邊(保證同樣兩個點間只會有一條邊)。
測資
輸出第K天時茵可會走到哪個點。
|
|
|
|
範例測資
第一天 0→1→2→3
第二天 0→2→3
第三天 0→4
第四天 0→1→4
一開始曲解題目了,不過沒關係。
首先讓我們來了解多久一循環,根據公式$cycle(u) = \sum cycle(v) | u \rightarrow v$,這個很容易理解的,事實上 cycle(0) 可能很大派不上用場。
如果試圖用週期 M 天,則期望用模擬迭代到 M 天是否與第一天相同,則很容易在 M + 1 天不會與第二天相同,因為路徑相同不代表狀態相同。
藉此我們利用動態規劃的概念,來找尋狀態的基底位置。
|
|
身為魔法師的你,想讓自己變得更強大,於是前來膜拜紅圓茵可,同時想請教他學習魔法的秘訣。經過日復一日的嘗試,你終於通過了柏油路,並且來到茵可家。「看在你這麼努力的份上,我就稍微指導你一下吧。」茵可說道。「所謂魔法,跟程式設計很像,就是一堆指令的結合。將分子移動、放熱、發光等等基礎的小魔法結合在一起,就會變成強大的魔法(像是防護罩就是控制空氣分子的移動,並使其重新排列成為堅固的結構,達到防禦的效果。)。所以說,腦中運算的能力是很重要的。」語畢,茵可大大丟給你一個題目:
給你N個數字,挑出其中兩個數字可以得到一個數字差(非負),而N個數字會有N*(N-1)/2個數字差,問第K大數字差是多少?
如範例輸入,數字差有6個,分別為9(10-1)、7(8-1)、5(10-5)、4(5-1)、3(8-5)、2(10-8),其中第5大的是3。
「等你能在1秒內解完這個問題再來找我吧!」隨後茵可打開比較大的門走掉了。
第一行有兩個正整數N,K
接下來有N個整數(0<=每個整數<=1,000,000,000)
測資
輸出第K大數字差
|
|
|
|
使用二分搜索答案,通常是查找第 K 小的元素,這題是換成第 K 大元素,那麼就反過來找,中間調校的時候要特別小心。
代碼效率是 O(n log^2 n)
,事實上可以壓成 O(n log n)
,因為中間的索引值肯定是單調的,不過要考慮組合問題,特別要小心同一個元素自減的結果。由於懶得判斷,複雜度高了點還是過了。
|
|
相信大家都知道紅圓茵可是誰,就不多介紹了。最近他有一個煩惱,身為一位大魔法師,每天都有成千上萬的人來膜拜他<( )>。因為人數實在太多了,這麼多人跑到他家膜拜他,害他都無法好好練習魔法了。茵可家門前有一條柏油路,要到他家一定得經過這條柏油路,他決定把這條柏油路(長方形)切成N*M個格子,並且在其中某些格子設下陷阱,踩到陷阱的人會被傳送回柏油路的起點。「恩~這樣子就可以減少膜拜我的人了~」紅圓茵可心想。但是,為了讓jackyXX等人可以到達他家,也不能把柏油路封死,必須確保一定有條路徑可以走到茵可家。而你的任務是要提醒茵可大大<( )>,哪些點能放陷阱,而哪些點不能放陷阱(導致道路封死)。
柏油路的起點在左邊,而茵可家在柏油路的右邊。一個人在柏油路上只能往上下左右四個方向走,不能走斜對角。
一條3*10的柏油路
oooooooooo
oooooooooo
oooooooooo
一條被封死的柏油路
ooooxooooo
oooxoooooo
ooxooooooo
一條沒被封死的柏油路
xxxxxxoooo
oooooxoxxx
ooxxoooxoo
第一行有3個正整數N、M、T,T為茵可接下來要放的陷阱數量(0<T<=N*M)。
接下來T行每行有2個非負整數x,y表示這個陷阱要放的位址。
縱軸為x軸,橫軸為y軸,左下角那格為(0,0)。
保證一個點只會被放最多一次。
測資
對每一個要放的陷阱,若該點可放,請輸出一行”<( )>”(不含雙引號),並且把陷阱放上去。
若該點不可放(會導致道路封死),請輸出”>_<”(不含雙引號),並且不放該陷阱。
|
|
|
|
這一題相當活用并查集的概念,雖然題目問說是否能左右相連,但是反過來則是上下邊界是否會從不相連變成相連。
多設兩個虛點,我們假想所有上界點都與虛上點相連,下界點都與虛下點相連,每次一次加入一個障礙物時,檢查九宮格內是否會造成上下虛點相連,這裡必須先偷看并查集的結果,隨後在考慮是否將其相連。
|
|
每一步轉角九十度,並且第 i 次要走 i 長單位,回到原點且沿途不經過障礙物,同時轉角不可重複。
|
|
|
|
沿途經過障礙物,同時轉角不重複。一開始曲解了經過的轉角點,以為他也不能在隨後中經過,但實際上是可以的,因此拿了不少 WA。
|
|