1. 程式人生 > 其它 >LOJ 2707「BalticOI 2015」拔河 / 3.14 校內考試 歡樂感 (happy)

LOJ 2707「BalticOI 2015」拔河 / 3.14 校內考試 歡樂感 (happy)

\(2n\) 個人,每個人可以選擇站左邊或者右邊,每邊有 \(n\) 個位置,每個人在左邊右邊都各自有一個想要站的位置,同時每個人都有一個力量值,現在給定一個整數 \(k\),問能否分出兩個隊,這兩邊各有 \(n\) 名選手,並且他們站在想站的位置(不能多人站在同一位置),並且雙方力量和之差不超過 \(k\)
\(k\le 20n,1\le l_i,r_i\le n,1\le s_i\le 20,n\le 3\times 10^4\)(考試時:\(n \le 8\times 10^4\)\(0.5s\)


  揹包 結論 動態規劃

  首先,如果一個人想站左邊的 \(a_i\) 位置,想站右邊的 \(b_i\)

位置,那麼我們可以將左部點 \(a_i\) 和右部點 \(b_i\) 連一條邊權為力量值的邊,然後可以發現,我們的問題轉化為將邊上的邊權分給一側的點,使得左部右部的點邊權之和的差不超過 \(k\)

  然後可以發現結論了:點數是 \(2n\) 的,邊數也是 \(2n\) 的,而且如果有一個點沒有連邊,那麼就是 NO,因此,這個圖是一個基環樹,然後可以簡單地畫圖發現,對於基環樹樹的部分,邊的分配方式是確定的,但是對於環的分配方式,可以有兩種選擇(順時針以及逆時針,注意這個環一定是一個偶環)。

  然後對於環的分配方式,我們會有兩種選擇,設每種選擇的值會讓左右兩邊有 \(\Delta\) 的差距,那麼我們可以使用揹包算出最小差距。

  原題可以直接使用 bitset 進行優化揹包然後過去。

  然後考試的時候被卡了,這個考慮一種更加快速的辦法,我們揹包的值域為 \(2sn\),那麼不同的數個數為 \(\sqrt{2sn}\),那麼可以直接二進位制分組優化多重揹包,然後再套一個 bitset 進一步加速,複雜度為 \(\mathcal O(\frac{(2sn)^{\frac{3}{2}}\log n}{\omega})\)

  程式碼