恐將成為我改題時間最長的一場(也是分最低的一場)
碼長斷崖式領先了
首先你肯定要讓小於(等於)中位數的數變小,將較大的值變小是毫無意義的,因為即使你完全不管他們,也不會對答案造成任何影響,白白浪費費用
可以考慮二分答案列舉中位數是啥,然後嘗試將前半段每個數都除到中位數以下,計算最小花費
可以注意到的是,如果一個數 \(a_i\) 除以 \(x\) 能到達中位數以下,那麼 \(\ge x\) 的數都能做到,這告訴我們兩點:一是可以二分答案求解這個 \(x\),二是我們應該在所有這些合法的裡面取一個費用最小值,對費用做字尾 \(\min\) 即可
然後由整除分塊經典結論,\(\lfloor{\frac{\lfloor{\frac{a}{b}}\rfloor}{c}}\rfloor=\lfloor{\frac{a}{bc}}\rfloor\),因此有可能提供的這個花費並不是最優花費,比如如果 \(cost_6\gt cost_2+cost_3\),這時用 \(6\) 就不如用 \(2\) 和 \(3\),因此考慮分解其質因數,用質因數花費之和來更新當前值的花費
需要注意的是值域並不只到 \(V\),一個 hack 是 \(V\) 很小,\(a_i\) 很大,值域開小了可能出現超過二分上界的問題(即一個數需要被除很多次)
線段樹分治
按照線段樹分治的思路直接做
這道題的難點在找到操作會影響哪些區間,上個結論
操作影響的區間一定形如若干連續段,且連續段不超過 \(\log\) 個
證明:考慮拆位,操作 \(s\) 滿足 \(s\operatorname{xor}x\lt K\),當且僅當存在某一位 \(i\),使得對於任意更高位 \(j\),\(s_j\operatorname{xor}x_j=K_j\),且 \(s_i\operatorname{xor}x_i=1,K_i=0\)
如果我們對詢問建一顆 Trie 樹,符合要求的詢問一定對應 Trie 上某個子樹,如果我們事先對詢問排序,那麼對應的就是一個連續的區間了,由於 Trie 深度最高 \(\log\),因此連續段也不超過 \(\log\) 個
因此,本題的方案就是:對詢問建立 Trie 樹,找到詢問區間,然後直接線段樹分治即可
按照題目給的 “每個人只能投給父節點” 投票,我們可以透過二分答案計算出一個最大得票數量的最小值(意思就是把票儘可能均攤給每個人,讓得票最多的那個人得的最小),記這個值為 \(s\)
記一個節點的子樹大小為 \(s_i\)(不包含自己,因為自己無法給自己投票),現在我們要想讓 \(i\) 贏,可以分成以下情況:
- \(s_i\gt s\),然而我們剛才得到的最大的票數量是 \(s\),說明 \(i\) 最多隻拿了 \(s\) 票,那麼子樹內就一定存在節點將票投給了 \(i\) 的祖先,現在這些節點將票收回來,都投給 \(i\),\(i\) 的票數只會增加(並最終大於 \(s\),因為 \(s_i\gt s\)),祖先的票數只會減少,最終 \(i\) 可能是勝出者
- \(s_i\lt s\),和上述情況類似,即使子樹內所有票都投給了 \(i\),仍然不滿足 \(s_i\ge s\),而子樹內更不可能有 \(s_i\ge s\) 的節點,但是現最大票數為 \(s\),說明子樹外一定有票數為 \(s\) 的節點,\(i\) 一定失敗
- \(s_i=s\),此時需要特殊判斷,這種情況下 \(i\) 想要勝出,可以先欽定最大票數只有 \(s-1\) 票,這樣多出來的票會彙集到根節點,此時欽定 \(i\) 獲得了 \(s\) 票,並且由於子樹外最大票數是 \(s-1\) 票,因此 \(i\) 自己那一票只能直接傳到根節點,否則不會勝利