NOIP2024集訓 Day47 總結

Saltyfish6發表於2024-10-08

前言

人有兩次生命,當他意識到只有一次的時候,第二次生命就開始

最小生成樹和二分圖匹配專題,感覺總體都比較套路。

但是這些套路為啥感覺見都沒見過啊,怪不得做這麼慢。

觀察到對於最終答案顯然都是最小生成樹上一條兩個端點顏色不同的邊。

而這個題並不會改變圖的形態,僅僅是改變顏色。

故你考慮維護每一個父親節點,每一種顏色的兒子都開一個 \(\text{multiset}\)(你可以開一個 \(\text{map}\) 來方便實現這個過程),在維護一個答案的 \(\text{multiset}\),維護的時候注意一下插入和刪除的細節即可。

複雜度 \(\mathcal{n\log^2 n}\),但是常數巨大。

\(\text{Code}\)

最小公倍樹

一個有趣的事實是,你考慮列舉 \(\text{gcd},1\to r\),然後在列舉它在 \([l,r]\) 之間的整數倍是哪些數,這一部分顯然是個調和級數,\(\mathcal{O}(n\ln n)\)

然後你看他們之間怎麼連邊,假設這些合法的 \(\text{gcd}\) 的整數倍分別是 \(a_1,a_2,...a_m\)

顯然,你考慮將 \(j\in[2,m]\) 連一條 \((a_j,a_1,\frac{a_j\times a_i}{\text{gcd}})\) 的邊即可。因為你本質上只需要將同一層的 \(\text{gcd}\) 連向最小的一個點即可,畢竟他和其他點連的邊權顯然是最小的。(這個 \(\text{trick}\) 其實出現在了後面的題目裡面,就是本質上你邊權相同的點你可以只連一個菊花,而沒有必要兩兩互相建邊,是非常重要的。)

另外,如果他不是最大的 \(\text{gcd}\),那麼使用它顯然不會更優,故這樣連邊不會出錯。

連邊之後直接跑 \(\text{Kruskal}\) 即可。

複雜度應該是 \(\mathcal{O}((r-l+1)\times (\ln r) \times (\log (r-l+1)))\)

\(\text{Code}\)

Power Tree

這個題題解區有透過差分而得到的非常巧妙的最小生成樹做法,這裡講一下自己輸出方案巨噁心的動態規劃做法。

定義 \(dp_{i,0}\) 表示將 \(i\) 子樹之下的葉子節點全部變為相同所需要的最少代價。

定義 \(dp_{i,1}\) 表示將 \(i\) 子樹之下的葉子節點可以變為任意數的最小代價。

顯然有轉移:

\(dp_{i,0}=\min dp_{j\in son_i,0}+\sum_{k\in son_i,k\not= j} dp_{k,1}\)

\(dp_{i,1}=\min dp_{j\in son_i,0}+\sum_{k\in son_i,k\not= j} dp_{k,1}+w_i\)

然後這個輸出方案巨噁心,因為你要把所有可能的都輸出。

\(\text{Code}\)

City 城市建設

非常重要且典的題,可是我根本不會,所以像我這種腦子不好使的人趕緊去學 \(\text{LCT}\) 吧。

你考慮對於操作詢問進行線段樹分治。

我們觀察到兩個性質。

  • 如果你將修改的邊賦為 \(\text{inf}\),跑完最小生成樹之後,此時不在樹上的邊一定不在最終的最小生成樹上。
  • 如果你將修改的邊賦為 \(-\text{inf}\),跑完最小生成樹之後,此時在樹上的邊一定在最終的最小生成樹上。

故你每次遞迴兒子的時候就只留下有用的邊,然後把一定會用上的邊先用並查集維護上,這樣你每次需要跑的點和邊都是這個區間的長度從而達到複雜度平衡。

時間複雜度 \(\mathcal{O}(q\log q \times \alpha(n))\)

\(\text{Code}\)

新年的繁榮

參考一下今天的第二題。

觀察到邊權並不會很大,你考慮 \(\text{Kruskal}\) 求最大生成樹的過程,從大到小列舉邊權,然後合併連通塊。

首先對於那些點權相同的點你可以相互之間直接合並,這樣顯然不劣。

然後你發現假設當前邊權是 \(x\),你考慮找到所有含有點 \(y,x|y\) 的連通塊。

觀察到這些連通塊顯然不超過 \(m\) 個,且每個連通塊中必然包含 \(x \lor 2^i\),如果不包含那我顯然可以在更高邊權的時候將 \(x\lor 2^i\) 合併進這個連通塊,顯然更優,如果超過了 \(m\) 個顯然透過鴿巢原理我仍然可以在更高位的地方合併。

所以你跑一遍類似高維字尾和的操作找到這些連通塊然後分別合併即可。

時間複雜度 \(\mathcal{O}(m\times 2^m\times \alpha(2^m))\)

\(\text{Code}\)

免費道路

一道比較智慧的題,但是我居然沒有想到,我是廢物。

你考慮先求出必須要用的鵝卵石路,即你在跑生成樹的時候,先跑水泥路,再跑鵝卵石路就可以得到。

然後你再跑一遍生成樹,先把必須要用的鵝卵石的路加上,然後先跑鵝卵石路再跑水泥路,鵝卵石路數量到了 \(k\) 個那就別再往生成樹裡面加鵝卵石路即可。

顯然這樣是對的,因為你用了必須用的鵝卵石路之後,不管你鵝卵石路後面怎麼取,水泥路都有辦法讓他變成一顆生成樹。

無解顯然只有三種情況:

  • 圖不連通。
  • 必須用的鵝卵石路 \(>k\)
  • 跑完第二遍生成樹之後,你儘可能多的用鵝卵石路仍然沒用到 \(k\) 條。

\(\text{Code}\)

Sorting a Grid

一道還不錯的建模題,大致是會的。

你先考慮合法的情況下, \(b,c\) 需要滿足什麼條件。

顯然,\(c\) 是必須讓每一行的數都包含了這一行最終應有的元素。

故你考慮將 \(x\) 染上 \(\lceil \frac{x}{m}\rceil\) 這種顏色,你發現合法的 \(b,c\) 滿足:

  • \(c\) 每行的顏色相同。
  • \(b\) 每列的顏色有 \(n\) 種。

顯然,對於 \(b\) 你可以透過求一個二分圖完美匹配得到。

觀察到每一個 \(b\) 顯然都會對應它唯一的 \(c\)

時間複雜度 \(\mathcal{O}(n^2m^2)\)

\(\text{Code}\)

全場唯一板子。你將 \((i+j)\) 為奇數的時候看成左部節點,為偶數的時候看成右部節點,然後跑一個最大獨立集即可。

\(\text{Code}\)

後記

撒花~

相關文章