2024.4 做題紀要

APJifengc發表於2024-04-07

aaaaaaaaaaaaaaaaa

大致是在成七集訓,雖然挺多都是 3 月底的不過還是整一下。

目錄
  • 2024.3.30
    • T2 簡單題
  • 2024.4.1
    • T3 木棍
    • AGC059E Grid 3-coloring
  • 2024.4.2
    • T1 斬首 (Gym104901F)
    • T3 戰爭
  • 2024.4.5
    • T3 Text
  • 2024.4.7
    • CF1707D Partial Virtual Trees
    • CF1874E Jellyfish and Hack

2024.3.30

T2 簡單題

給定正整數 \(n\),定義集合 \(S = \{1, 2, \cdots, 2n\}\),求一個大小為 \(n\) 的子集,滿足兩兩不存在倍數關係且和最小,輸出最小的和。

\(n \le 5 \times 10^5\)

我感覺這種題應該見過不少次了,不過見到還是不會做,流汗。

但是這題好像各種貪心都能過,流汗。

考慮將數寫成 \(k 2^d\) 的形式,注意到如果有兩個數的 \(k\) 相同,那麼它們必定存在整除關係,所以 \(k\) 一定互不相同。而 \(k\) 一定是奇數,於是這 \(n\) 個數的 \(k\) 就一定是 \(1, 3, \cdots, 2n - 1\) 的一個排列。那麼我們相當於考慮最小化 \(d\) 了。記這些 \(d\)\(d_k\)。注意到對於任意一個數 \(p\) 來說,如果 \(d_{k} \le d_{pk}\) 的話,那麼這兩個數就一定存在整除關係了,所以必須滿足 \(d_{k} > d_{pk}\)。發現 \(d_k\) 應當是一個單調不增的東西,可以直接倒著用最緊的限制 \(d_{k} > d_{3k}\) 找到每個 \(d_k\) 的最小值,容易發現這組 \(d_k\) 是合法的,於是就得到答案了。

2024.4.1

T3 木棍

\(n\) 根長度相同的木棍,長度均為 \(k\),每個木棍要放置在 \([l_i, r_i]\) 的區間內,要求木棍兩兩不能重疊。此外還有 \(m\) 條額外限制,要求 \([x_i, y_i]\) 區間內的木棍最多有 \(c_i\) 根。

\(n, m \le 1000\)\(l_i, r_i \le 10^9\)

首先顯然可以把線段轉化成點,滿足每兩個點之間距離至少為 \(k\)

\(b_i\) 為第 \(i\) 個位置是否有木棍的 01 序列,那麼這些限制都可以寫成若干個區間和小於等於 \(c_i\) 的限制,而合法的 \(b_i\) 一定滿足存在匹配,可以 Hall 定理轉化成每個區間和大於等於區間內完全包含的待放區間數。而還有相鄰兩個數之間距離至少為 \(k\) 的限制,這可以看作是每個長度為 \(k\) 的區間和 \(\le 1\),加上每個長度為 \(1\) 的區間也 \(\le 1\),這樣我們的所有限制就都轉化成了每個區間和的限制。

考慮如何限制區間和,字首和一下,發現限制就變成了若干 \(p_r - p_{l-1} \ge c\)\(p_r - p_{l-1} \le c\) 的形式,容易想到差分約束。我們建一排點,分別表示字首和後的 \(p\),然後此時我們有若干向前和向後連的邊。我們把邊分為三類,第一類是 Hall 定理得出的限制,設 \(h(i, j)\) 表示 \([i, j]\) 內包含多少待放區間,那麼對於所有 \(i < j\)\(j\)\(i\) 連邊權為 \(-h(i, j)\) 的邊。第二類邊是由 \(k\) 得出的限制,對於任意 \(i<j\)\(i\)\(j\) 連邊權為 \(\lceil\frac{j - i}{k}\rceil\) 的邊,第三類邊就是所有 \(x_i\)\(y_i\) 連邊權為 \(c_i\) 的邊。

首先要解決的問題是,現在點數是關於值域的,肯定沒法直接跑。注意到我們只關心這張圖存不存在負環,所以我們儘可能最小化環的長度。首先對於這兩個貢獻函式來說,都有 \(f(i, j) + f(j, k) > f(i, k)\),也就是說連續走兩條第一類或第二類邊是不優的。而 \(h(i, j)\) 只在離散化後的陣列上的位置會發生變化,所以我們一定能調整第一類邊的端點到離散化陣列上的值,那麼也就是說如果存在負環,那麼一定存在只經過離散化後的陣列上的點的負環,於是我們就可以放心的在離散化後的陣列上做了。直接跑差分約束即可做到 \(O(n^3)\) 了。

考察正常 Bellman-Ford 演算法,我們令 \(f_{ku}\) 表示經過 \(k\) 步後到 \(u\) 的最短路,如果 \(f_{n, u} = f_{n + 1, u}\) 則沒有負環。那麼我們考慮快速從 \(f_{k, *} \to f_{k+1, *}\)。首先第三類邊是最容易處理的,暴力轉移即可。第一類邊的貢獻函式是 \(h(i, j)\),就是 NOIP2023 T4 的做法直接掃描線即可。第二類邊的貢獻函式帶上取整,不太好處理。發現我們可以用 \(\lfloor\frac jk\rfloor - \lfloor\frac ik\rfloor\) 來估計 \(\lceil\frac{j-i}{k}\rceil\),誤差只與 \(i \bmod k, j \bmod k\) 有關,於是可以以 \(i \bmod k\) 為下標建線段樹來做這個貢獻。總之兩種貢獻都可以 \(O(n \log n)\) 最佳化轉移。於是總複雜度為 \(O(n^2 \log n)\)

AGC059E Grid 3-coloring

我真的是抽象完了的做法。真的以後不瞎寄吧編做法了,做這題給我做吐了。

相鄰兩個位置不相等是一個很抽象的的條件,考慮轉化一下,把顏色看作 \(\bmod 3\) 意義下的數,然後將第 \(i\) 個對角線加上 \(i\),這樣上下或左右兩個位置之間要不然顏色相同要不然正好減 \(1\)。這相當於要求從任意一個點向右下走只能減 \(1\) 或不變。畫一下圖,容易發現最後的矩形由若干條從左下到右上的路徑劃分開。

img

我們把右上邊框和左下邊框分成兩部分,那麼這個矩形就可以看作是左下邊框到右上邊框的若干條路徑。注意此時左下與右上是若干連續段,我們考慮保留一段連續段中最靠中間的點,然後轉化成這些點之間的路徑,容易發現這兩者是等價的。需要注意兩個連續段內要求任意兩點都是可以透過向右、上、右上走達的,所以如果兩個段的左端點或者右端點之間不能互達那麼就是無解的,需要先把這種情況判掉。

img

(關於等價的證明:對於左邊框來說,由於靠上的段只能往上走,於是不會影響下面的段,所以我們只需要考慮這個連續段中最靠下的那個點能否到達右上角對應的段即可,顯然透過這條路徑劃分的連通塊內是包含整個連通塊的。如果經過中點,我們考慮先把在中點往上的路徑與中點往右的路徑全部填好,此時只需要中間存在一條路徑,就可以保證這個連續段內任意一個點都可以到達對面的點,所以只需要保留中點。)

那麼現在問題轉化成了,給定一個 \(n \times n\) 的網格圖,有 \(k\) 個起點與終點,分別位於左下邊框與右上邊框,問是否存在 \(k\) 條點不相交的路徑。

我們可以轉化成流的問題,可以容易的建出流圖:

img

其中斜著的一對點是由一個點拆點得到的,為了限制一個格子至多走一次。黑色邊是起點與終點的邊,這些邊容量可能為 \(0\)\(1\),對應著這裡有起點或沒有起點。

我們的目的就是求出這張圖的最大流。注意到這是一張平面圖,我們考慮建其對偶圖求最短路即可。

這裡需要說明的一點是,我從網上找到的一些資料,全部都只提到了將邊旋轉後建出圖,但是實際上在有向圖的情況下,這樣的圖的最短路並不一定就是最小割,因為最小割並不一定在對偶圖上形成連續的一條路徑。所以我們還需要將對偶圖所有邊建一條反向的邊權為 \(0\) 的邊,此時對偶圖的最短路才等於原圖的最小割,即最大流。

建出對偶圖:

img

其中綠色邊地邊權對應著這一塊有沒有起點,其它的橙色邊邊權均為 \(1\),且有反向 \(0\) 的邊權。

觀察對偶圖可以發現,中間的點也可以看作是拆點,然後可以向右、下、右下走。注意到向下、右走都可以走一條反邊加一條正邊,而向右下走至少經過兩條邊,所以此時向右下的邊是沒有意義的,所以我們實際上只會向下或向右。那麼我們列舉在邊框上的起點和終點,那麼我們就能知道最短路了。由於在邊框上走一定比在中間走更優,所以我們在中間部分一定只會往右或只會往下走,那麼這樣我們就只有 \(O(n)\) 條路徑需要判斷了,直接判即可。最後判斷最小割是不是等於 \(k\) 即可。

2024.4.2

T1 斬首 (Gym104901F)

考慮求出字首答案 \(f_i\) 和字尾答案 \(g_i\),那麼每個點的答案就是 \(\sum_{l=1}^i \sum_{r=i}^n f_{l-1} g_{r+1} [r-l+1 \ge \max_{k \in [l, r]} a_k]\)

考慮怎麼算 \(f_i\),發現這玩意算不了一點,由於限制裡有最大值,那麼就考慮分治,\(\max(ml_l, mr_r) \le r - l + 1\) 可以拆成二維數點。

然後考慮怎麼計算答案,同樣可以分治,處理所有經過當前分治中心的 \([l, r]\)。假設 \(i\) 在左區間,那麼考察 \(ml\) 發生什麼變化,發現如果 \(i\) 在單調棧上就會將一個區間內的 \(ml\) 修改,否則不變。注意到每個 \(ml\) 只對應一個 \(i\),那麼就可以直接暴力了。拿總答案再加上 \(ml\) 發生變化的一段的變化量即可。複雜度 \(O(n \log^2 n)\)

T3 戰爭

有一棵 \(n\) 個點的樹,樹有邊權,初始全為 \(0\)。有 \(m\) 個時刻,每個時刻進行一次操作,操作有兩種:

  • 1 x y \(x\)\(y\) 的鏈上加 \(1\)
  • 2 t 撤銷第 \(t\) 時刻的操作(保證一定是第一種操作且沒有被撤銷過)。

現在有 \(q\) 次詢問,每次詢問 \([l, r]\) 時刻內,邊權始終 \(\ge 1\) 的深度最大的邊。定義邊的深度為兩個端點到根經過的邊數的較大值。

\(n, m \le 10^5, q \le 5 \times 10^5\)

考慮一個部分分,\(x=1\),即所有鏈加操作都是根鏈。考慮找出每個操作的存留時刻的區間 \([l, r]\),那麼對於某一條邊來說,其存留時刻就是子樹內所有區間的並。對於每一條邊來說,得到的邊數肯定還是 \(O(n)\) 的,所以我們不能直接找出每條邊的所有區間。注意到我們只關心深度最深的邊,那麼我們只用考慮每個區間的最早的一次形成即可。我們直接樹上啟發式合併,每插入一個區間就會與原來的若干區間併成一個新區間,這樣我們就能得到 \(O(n \log n)\) 個區間了,然後就是一個矩形 \(\max\) 單點查詢了,時間複雜度 \(O(n \log^2 n + q \log n)\)

考慮 \(x \ne 1\) 的情況也是簡單的,我們改成用線段樹維護區間並,這樣我們就可以進行撤銷操作了。每次插入一個區間後,線上段樹上二分找到所在的最長的區間,剩下的做法和 \(x=1\) 的相同了。

2024.4.5

T3 Text

給定一個長為 \(n\)、值域為 \(m\) 的字串 \(s\),多組詢問,求字典序小於等於 \(s\) 的長為 \(l\) Lyndon 串數。模數由輸入給定。

\(n \le 10, m \le 1000, l \le 5 \times 10^6\)

這題好牛啊。

首先對於字串 \(s\),考察其 Lyndon 分解,那麼對於任意一個字典序小於等於串 \(s\) 的 Lyndon 串,其字典序一定小於等於 Lyndon 分解的第一個 Lyndon 串。於是我們可以只保留 \(s\) 的字首最長 Lyndon 串。

然後對於任意一個字串,考慮其與字串 \(s'=sssssss\cdots\) 的大小關係,對任意一個字串進行 Lyndon 分解後,第一個 Lyndon 串一定小於等於 \(s\),而 Lyndon 串分解不增,於是所有分解出的串都小於等於 \(s\)。反過來,所有串均小於等於 \(s\) 的串也小於 \(s'\)

那麼我們就得到了一個充要條件:一個串小於等於 \(s'\) 當且僅當其 Lyndon 分解的每一部分小於等於 \(s\)

那麼我們就可以上 Euler 變換,設 \(F(x)\) 為小於等於 \(s\) 的 Lyndon 串數,\(G(x)\) 為小於等於 \(s'\) 的串數,那麼就有 \(G(x) = \prod_i (\frac{1}{1-x^i})^{f_i}\),施 Euler 變換即得 \(\ln(G(x)) = \sum_{i \ge 1} \frac{F(x^i)}{i}\),設 \(H(x) = \ln G(x)\),提取兩邊係數可以得到 \(n h_n = \sum_{k | n} k f_k\),莫比烏斯反演得到 \(f_n = \sum_{k | n} \mu(\frac nk) k h_k\),這部分可以直接 \(O(2^{\omega(n)})\) 反演得到。

剩下的問題就是計算 \(H(x)\),考慮小於等於 \(s'\) 的串有多少,可以列舉第一個不相同的位置,那麼相當於將兩部分卷積起來,前一部分是 \(s'_i - 1\),後一部分是 \(m^i\)。設 \(S(x) = \sum_{i=1}^n (s_i - 1) x^i\),那麼 \(s'\) 對應的就是 \(\frac{S(x)}{1-x^n}\),那麼答案就是 \(\frac{S(x)}{(1-x^n)(1-mx)}\),注意到還有完全相等的情況,所以還要加上一個 \(\frac{1}{1-x}\),那麼就有 \(G(x) = \frac{S(x)(1-x) + (1-x^n)(1-mx)}{(1-x^n)(1-mx)(1-x)}\),這是一個次數 \(O(n)\) 的分式,我們要求 \(\ln G(x)\),直接 ODE 線性遞推一下即可。

2024.4.7

CF1707D Partial Virtual Trees

感覺是這個感覺,但是沒懂怎麼設計狀態,菜了。

集合序列不好刻畫,考慮用一組序列 \(t_i\) 來表示這個集合序列,其中 \(t_i\) 表示第 \(i\) 個點被刪除的時刻。容易發現根據這個序列即可得到一組集合序列。但是這樣並無法保證真子集的限制,我們可以容斥一下,先計算可以相等的方案,然後再容斥一下,是個二項式反演的形式,直接做一下。現在考慮怎麼做這個。

\(p_u\) 為子樹內的 \(t_i\) 最大值,虛樹的限制實際上是,如果一個點有至少兩個子樹內有點,那麼這個點就不能被刪除,即不存在兩個子樹內 \(p_v\) 均大於 \(t_u\) 的情況。那麼考察 \(t_u\) 與子樹內 \(p_v\) 的大小關係,有兩種:

  • \(t_u \ge \max p_v\)
  • \(t_w > t_u \ge \max_{v \ne k} p_v\)

我們設 \(f_{u, k}\) 表示 \(u\) 子樹內 \(p_u = k\) 的方案數,那麼根據上面兩種情況有兩種轉移:第一種是 \(f_{u, k} \gets \prod_v (\sum_{i \le k} f_{v, i})\),第二種是 \(f_{u, k} \gets \sum_{j < k}\prod_{v \ne w} (\sum_{i \le j} f_{v, i}) f_{w, k}\),簡單最佳化一下即可 \(O(n^2)\)

CF1874E Jellyfish and Hack

有點流汗。nfls 考過一個類似的題,而且是在這之前,題目與解法的重合度比較厲害,,

反正就是直接 DP 然後插值最佳化就好了,複雜度 \(O(n^4)\)

相關文章