2021/12/31 校內比賽

seketsu發表於2022-01-16

Problem D

其實是道很簡單的二分題但考場上我一直想的是貪心。

每一次操作,任選一個不變其餘減 \(1\)

那麼二分答案,對於二分到的答案 \(mid\),我們計算 \(\sum\limits_{a_i<mid}(mid-a_i)\),如果小於等於 \(mid\) 就是合法答案。

時間複雜度 \(O(n\log n)\)


Problem H

很容易想到的一個逆向思維是,所有的人不動,而是電線杆動。

那麼怎麼解決電線杆與分身的碰撞呢?我們以橫向運動為例。

假設電線杆現在在 \((x_0,y_0)\) 點,要向右移動距離 \(l\),那麼根據題意,滿足 \(x\in[x_0,x_0+l]\) \(y=y_0\) 的分身都會被合併到點 \((x_0+l+1,y_0)\) 上。

合併直接用並查集即可,關鍵在於如何找到這些該合併的點。

我們考慮以 \(x\) 升序最為第一關鍵字,\(y\) 升序作為第二關鍵字排序,不難發現的是,我們需要的點在一個區間上。

由於需要動態維護,我們用 set 維護,操作的時候 lower_bound 找到所需區間第一個點即可。

同理,處理上下移動時,我們需要以 \(y\) 升序最為第一關鍵字,\(x\) 升序作為第二關鍵字排序,需要再來一個 set

對於時間複雜度,類似於啟發式合併,是 \(O(n\log n)\)


Problem I

分情況討論:

  • 不在最短路上,且邊變大:一定不會是新的最短路。
  • 不在最短路上,且邊變小:將經過這條邊的最短路與原來的最短路比較即可。
  • 在最短路上,且邊變小:原來的最短路減去對應差值即可。
  • 在最短路上,且邊變大:新的最短路可能是原來的最短路加上這段差值,也可能是刪掉這條邊做最短路。

因此,這道題中最複雜的部分其實就是如何做刪邊最短路。

我們先隨便取出一條最短路,形成一條鏈。類似於斷環法的思路,我們考慮刪掉這條鏈上的一條邊之後,以一條路徑繞過這條邊。

比如一條路徑從 \(x\) 點從這條鏈出去,從 \(y\) 回來,那麼這條路徑就能作為 \(x\)\(y\) 鏈上所有斷邊的"替代"。

按照這個思路,我們列舉每一條邊 \((u,v,w)\),嘗試用 \(d_1(u)+d_2(v)+w\) 來更新對應的區間。由於到 \(u\) 是用的最短路(即 \(d_1(u)\)),因此我們在\(x\) 點的時候也要滿足最短路的要求(即 \(1-x-u\) 的最短路就是 \(1-u\) 的最短路),再跑一遍最短路就可以完成找 \(x\) 點。找 \(y\) 點的時候同理。

由於只需要區間取最小值,我們用線段樹維護即可。

時間複雜度 \(O(n\log n)\)


Problem M

這好像是我做過的原題,但是時間太久遠了我給忘了。

考慮到 \(n\) 很小,我們可以列舉行的所有狀態,再列舉列貪心選擇(\(1\)\(0\) 多就翻),時間複雜度是 \(O(2^nm)\),需要優化。

\(a_i\) 表示狀態為 \(i\) 的列的個數,\(b_i\) 表示在列在狀態 \(i\) 時貪心選最少的 \(1\) 的個數。

舉個例子,對於狀態 \(10111100\)\(b_i=3\);對於狀態 \(00010100\)\(b_i=2\)

那麼我們列舉行的狀態 \(T\),有:

\[ans=\min_T\sum_{T\bigoplus i=j}a_ib_j \]

由於 \(T\bigoplus i=j\)\(i\bigoplus j=T\) 等價,轉化成:

\[ans=\min_T\sum_{i\bigoplus j=T}a_ib_j \]

後半部分是 FWT 的模板,直接做即可。

要注意的是,雖然答案在 \(nm\) 以內,但是做的時候可能會超 int 範圍,要開 long long

時間複雜度 \(O(n\log n)\)

相關文章