TIOJ 1852 分眼皮

Description

你有 n 張眼皮和三隻向姊,每張眼皮有他的角動量。
你希望把這些眼皮全部分給三隻向姊,為了避免眼皮爆走,所以需要讓向姊間的角動量差最小,否則向姊們就會吵架!
(假設所有眼皮轉動方向都是逆時針方向,且對於每隻向姊,她的所有眼皮的旋轉中心都相同)

Input Format

1 行有一個數字 n (3n24),代表眼皮的個數。
2 行有 n 個數字 a1,,an1ai109,代表每張眼皮的角動量。

Output Format

輸出一個數字,代表角動量最大的向姊和角動量最小的向姊間的角動量差的最小值。

Sample Input

4
5 4 7 6

Sample Output

3

Solution

如果今天只有兩隻向姊,怎麼做呢?利用 meet-in-the-middle algorithm,可以做到 O(n2n/2) 的時間複雜度,比 naïve 演算法的 O(2n) 快。以下將介紹怎麼在有三隻向姊的情況下,同樣利用 meet-in-the-middle 的精神,在 O(n3n/2) 時間內求出答案。為了後續的討論方便,我們允許某個 ai0,且允許某隻向姊沒分到任何眼皮。

假定三隻向姊拿到的眼皮角動量總和分別為 p,q,r,不失一般性令 pqr,目標最小化 rp。設 s:=a1++an,則以下的兩個敘述至少一個會成立:
  1. pqs/3r
  2. ps/3qr
如果我們知道怎麼算出第一種情況 rp 的最小值,只要把每個 ai 變號,第一種情況 rp 的最小值就變成「變號前的第二種情況 rp 的最小值」了。接下來我們專注在「在限制 pqs/3r 下最小化 rp」上。

a1,,an 分成兩堆,A={a1,,an/2}B={an/2+1,,an} (這裡 AB 都是 multiset)。對 AB,各自枚舉有哪些眼皮分給第一隻和第二隻向姊,時間複雜度 O(n3n/2) (或 O(3n/2),如果你要優化它的話 XD)。假定有一種選法,第一隻和第二隻向姊分別在 B 中拿了角動量總和為 ξη 的眼皮。設兩隻向姊分別在 A 中拿了角動量總和為 xy 的眼皮,則根據 pqs/3,有 {ys/3η,xy+ηξ. 注意 (1) 其實就是下圖的陰影部分 K(s/3ξ,s/3η),包含邊界:
兩隻向姊只能拿陰影部分的 (x,y)
另一方面,固定 (ξ,η),則 rp 的最小值就是 min{rp}=min{(spq)p}=min{s2pq}=min{s2(ξ+x)(η+y)}=s2ξηmax{2x+y}. 所以問題就被轉成:給定 R2N:=3n/2 個點 P:={(xi,yi)}Ni=1,其中 (xi,yi) 有權重 wi:=2xi+yi。現在有 M:=3n/2 筆詢問 {(xi,yi)}Mi=1,對詢問 (xi,yi) 要回傳 PK(xi,yi) 裡的最大權重 (如果不存在則回傳 )。這個問題可以用一條斜率為 1 的掃描線 (sweep line) 搭配 BIT (binary indexed tree) 做到 O((N+M)logN)=(n3n/2) 的時間複雜度,也就是整體的時間複雜度是 O(n3n/2)
藍點為 N 筆資料,紅點為 M 筆詢問。往右移動橘色這條掃描線,記錄每個藍點 y 值目前遇到的最大權重,並建立 BIT 來支援 O(logN) 查詢與修改。
這個題目問的是向姊有三隻的情形。如果向姊變成四隻,該怎麼做呢?好問題,我也不知道 wwwwww

我的 code:
https://ideone.com/CMTdMh

然後聽說這題的官方解法是爆搜 + 剪枝,囧。

(2018-05-04 補記)

想想後發現其實不需要討論 qs/3 的大小關係。由 pqqspq,固定 (ξ,η),則兩隻向姊在 A 中能拿到的 (x,y) 區域變成 K(ξ,η):={(x,y)R2:xyηξ,x+2ysξ2η}. 注意 K(ξ,η)={(s3ξs3η)+α(21)+β(11):α0,β0}. 因此只要一個座標變換,就能用垂直掃描線和 BIT 做到 O(n3n/2) 的時間複雜度,詳細部分可以直接參考我的 code:
https://ideone.com/7u8TS2

這個方法可以推廣到向姊有 k (k4) 隻的情況,時間複雜度是 O(nk2kn/2),不過實作上很麻煩 (我的方法要用到 k2 層的 binary search tree),又不怎麼實用 orz。

留言

這個網誌中的熱門文章

2020 全國賽驗題心得

水母上 Divide-and-Conquer

109 學年度全國資訊學科能力競賽各題詳解