2024.4.3
\(40+100+40=180\)。今天過了一題/開心
草了,T2 空間開大 MLE 了,實際上只過了 \(0\) 題,如果不算這個就登頂了
fibonacci
首先答案一定可以在 \(S_{31}\) 中找到。具體地,找到最大的 \(i\) 使得 \(S_{i-4}< 3|t|\),取 \(S_i\) 即可。
這是因為首先任意三個相鄰位置都至少有一個 a
一個 b
,因為這個過程可以看做 \(a\to ab,b\to a\),或者歸納也可以證明。那麼答案串 \(ans\) 滿足 \(|ans|\le 3|t|\)。然後如果 \(S_{i-4}\ge 3|t|\),那麼
如果答案可以在 \(S_i\) 中找到,要麼 \(ans\in S_{i-2}\),或者 \(ans\in S_{i-1}\),或者 \(ans\) 跨過了 \(S_{i-1},S_{i-2}\) 中間的分割線。然後由於 \(S_{i-4}\ge 3|t|\ge |ans|\),因此 \(ans\) 不可能跨過 \(+\) 左右兩側的 \(S_{i-3}\) 或 \(S_{i-4}\),由於 \(S_{i-3}S_{i-4}=S_{i-2}\),因此 \(ans\) 仍然被包含在 \(S_{i-2}\) 中。於是 \(S_i\) 就沒有用了。
具體地,有 \(|S_{28}|=514229\ge 450000\),於是我們取到 \(S_{31}\) 即可。看上去取 \(S_{30}\) 也能過
設 \(to_{i,j}\) 表示 \(S_i\) 這個串,從 \(t_j\) 開始走,會走到哪個 \(t_k\)。\(to\) 可以遞推得出。
考慮雙指標,考慮如何 check 一個區間能否走完 \(t\)。建一個類似 segtree 的結構,把區間拆成 \(O(\log t)\) 個完整的 \(S_j\),利用 \(to\) 判斷即可。
複雜度 \(O(|t|\log |t|)\)。常數大概有很多倍。跑的賊慢,喜提最劣解。
tap
這不是我們 PA2024 kra 嗎後面忘了
後面是:
只需要求能到達每個區間的區間個數。
對每個區間 \([l,r]\),找到 \(l\) 上面的第一個區間和 \(r\) 上面的第一個區間,然後分別連邊,得到兩棵樹。
那麼我們會從 \([l,r]\) 一路向上擴充套件,直到被完全覆蓋。找到這個完全覆蓋的,那麼合法區間就是覆蓋過程中經過的若干段陰影區域拼起來。倍增求一下鏈上和就好了。
這裡還需要求第一個被覆蓋到的區間,發現這就是支配樹上它的父親,只需要求 DAG 的支配樹。這個很好求:任取拓撲序,對每個 \(u\),其入邊分別為 \(v_1,v_2,\cdots,v_k\),找到 \(\text{LCA}(v_1,v_2,\cdots,v_k)\),則 \(u\) 的支配點就是這個 LCA。連邊接著遞推即可。
跑得賊快,喜提最優解。
哦,這個題還有一個前面:他是每次隨機一個未選中的,然後選中它。這個等價於隨機排列,每次如果已經被覆蓋了就跳過。也等價於每次在 \(n\) 個裡面隨機,如果遇到了覆蓋過的就跳過。
polygon
首先介紹處理實數隨機的一些方法:把每個數拆成整數部分和小數部分,看成 \(x_i=y_i+z_i\),其中 \(y_i\) 是 \([0,2^{a_i}-1]\) 中的一個隨機整數,\(z_i\) 是 \([0,1)\) 中隨機的一個實數。
考慮怎麼算 \(n\) 個 \([0,1]\) 中的隨機實數加起來 \(\le k\) 的機率,嗯這個當然可以類似我場上寫的 6KB 維護分段多項式,\(O(n^2)\) 算出來。說不定強大的 poly 也可以把這個最佳化到 soft O(n)
考慮寫一下這個式子,他就是
然後他等於
額當然由於是實數所以取等啥的都無所謂。然後再拆開,需要算一些
然後這個你每次積分,就得到,他其實是 \(\frac{(k-j)^n}{n!}\)。然後一遍卷積就可以 \(O(n\log n)\) 算出 \(P_k=\mathbb{Pr}\left[\sum z_i\le k\right]\)。
接下來考慮整數部分。數位 DP,初值設為 \(dp(0,j)=P_{j+1}-P_j\),就表示我在第 \(0\) 位上放 \(j\) 個 \(1\)。剩下的我們都很熟悉。(NOIP2021 T2 / QOJ8009)卷積最佳化一下即可。複雜度 \(O(an\log n)\)。
其實程式碼我不太想寫......已加入《實在沒事幹了.md》
ICPC Nanjing 2023 D
\(f(u,j)\) 表示 \(u\) 子樹內,每個點到葉子都有 \(j\) 個黑點的最小代價。
那麼每次是把兒子的 \(f\) 直接相加,然後和 \(x_{u,0/1}\) 做 min+ 卷積,其中 \(x_{u,c}\) 表示將 \(u\) 點改成顏色 \(c\) 的最小代價。
顯然 \(x\) 也凸,那麼 \(f\) 自然就是凸的。
slope trick 隨便做做,這裡合併的時候可以用長剖合併,複雜度是 \(O(n\log n)\)。
然後也存在 \(O(n)\) 做法,大概是利用 \(x_u\) 的斜率是 \(1\) 或 \(-1\),分別維護正負兩邊的兩個 deque 等等。
ECFinal 2023 C
啊啊怎麼是這個題
考慮給每個合法序列 pair \((x_{1\cdots p},y_{1\cdots q})\) 對應唯一的一個加數的順序,每次如果當前 \(\sum x<\sum y\) 就加一個 \(x\),否則加一個 \(y\)。那麼每種方案對應唯一的順序,且每個順序中,\(\sum x-\sum y\) 的值永遠在 \([-V,V]\) 之間。
於是 \(dp_{i,j,k}\) 表示加入了 \(x_{1\cdots i},y_{1\cdots j}\),目前 \(\sum x-\sum y=k\) 的方案數即可。
每次如果 \(k<0\) 就轉移到 \((i+1,j,\cdot)\),否則轉移到 \((i,j+1,\cdot)\)。轉移用字首和最佳化,複雜度 \(O(n^2V)\)。
subset sum in O(nW)
是這樣,給 \(n\) 個 \([0,W]\) 中的數 \(x_1,\cdots,x_n\),然後給 \(T\in[0,nW]\),問能否選一個子集 \(S\) 使得 \(\sum_{i\in S}x_i=T\)。
這個問題還有更強的版本(QOJ7403,max subset sum <= T),然後這兩個其實是等價的。
先來解決弱的版本,貪心選取一個子集 \(A\) 使得 \(A\) 任意加入別的元素都會導致子集和 \(>T\),且 \(\sum_{i\in A}x_i\le T\)。這裡 \(A\) 可能不唯一,我們任取一個就好。接下來設 \(B=\{x_1,x_2,\cdots,x_n\}-A\),設 \(T'=T-\sum_{i\in A}x_i\),則 \(T'\in[0,W)\)。我們需要選取 \(C\subseteq A,D\subseteq B\),使得 \(\sum_{i\in D}x_i-\sum_{i\in C}x_i=T'\),那麼我們就得到一種方案 \(A-C+D\)。
仍然把一種方案唯一對應到一個加入順序,每次如果當前的和 \(<T'\) 我們就加入一個 \(D\) 中元素,否則加入 \(C\) 中元素。得到 DP:\(f(i,j,k)=0/1\) 表示 \(A\) 的前 \(i\) 個元素,\(B\) 的前 \(j\) 個元素,能否選出 \(\sum_{i\in D}x_i-\sum_{i\in C}x_i=k\) 的子集 \(C,D\),其中 \(k\in[T'-W,T'+W]\)。方便起見設 \(A=\{a_1,a_2,\cdots,a_{|A|}\},B=\{b_1,b_2,\cdots,b_{|B|}\}\),那麼轉移有:
這個做法的複雜度仍然為 \(O(n^2W)\)。
注意到有單調性:若 \(f(i,j,k)=\texttt{true}\),則任意的 \(p\ge i,q\ge j\) 均有 \(f(p,q,k)=\texttt{true}\)。考慮設 \(g(i,k)\) 表示最小的 \(j\),使得 \(f(i,j,k)=\texttt{true}\)。
照抄兩種轉移,發現 \(i\) 的轉移比較簡單,當 \(k\ge T'\) 時我們直接將 \(g(i,k)\to g(i+1,k),g(i+1,k-a_{i+1})\) 即可;但 \(k<T'\) 的時候我們似乎要列舉 \(j\ge g(i,k)\),然後做轉移 \(j+1\to g(i,k+b_{j+1})\)。
額,這好像還是 \(O(n^2W)\)。
注意到 \(g(i,k)\ge g(i+1,k)\),考慮做第三種轉移的時候,如果 \(j\ge g(i-1,k)\),那麼我們實際上已經轉移過 \(j+1\to g(i-1,k+b_{j+1})\to g(i,k+b_{j+1})\) 了,所以只需要列舉 \([g(i,k),g(i-1,k)-1]\) 之間的 \(j\) 去做轉移。
這樣對於每個 \(k\),列舉的 \(j\) 的總量就是 \(O(n)\) 的,於是總複雜度 \(O(nW)\)。
那麼 max subset sum <= T 怎麼做呢。注意到當 \(T\) 不超過所有數之和時,答案和 \(T\) 的差不會超過 \(W\)。於是我們類似地做一遍 DP,然後找到不為 \(\infty\) 的狀態來更新答案即可。
https://qoj.ac/submission/376872
CF1810G
看到這個題當然我們就想從前往後 DP,\(dp(i,sum,mx)\) 表示前 \(i\) 個數,和為 \(sum\),字首最大值為 \(mx\)。但是複雜度是 \(O(n^3)\),也不知道能不能最佳化。
考慮如果只需要算全域性的答案,那麼我們可以倒著 DP,\(dp(i,mx)\) 表示 \(i\cdots n\) 這些數,字首最大值為 \(mx\)。那麼往前加一個 \(+1\) 就是 \(mx\leftarrow mx+1\),否則就是 \(mx\leftarrow \max(mx-1,0)\)。
但是我們要算每個字首的答案,怎麼辦呢。考慮相當於有一個 \(O(n^2)\) 個節點的圖,\((i,j)\) 就表示一個狀態 \(dp(i,j)\),然後我們在 \((1,j)\) 這裡連一條 \(\times h_j\) 的邊到 \((0,0)\),那麼就是要算每個點到 \((0,0)\) 的所有路徑的邊權乘積之和。倒過來 DP 即可。
這個也可以說成,額,轉置原理?不太明白呀
這個題 luogu 題解區也有很多精彩做法口牙
ARC168E
那我們肯定想設 \(w(l,r)=\left[\sum_{i=l}^ra_i\ge s\right]\),然後求一下 \(w\) 自己做 max+ 矩乘 \(k\) 次冪的值嘛。但是不管是哪個方向的四邊形不等式,\(w\) 都沒辦法滿足。所以這完全不凸,全錯了。
\(w\) 不滿足四邊形不等式的反例:\(s=2,a=(1,1,1)\Rightarrow w(1,2)+w(2,3)>w(1,3)+w(2,2)\);另一方面取 \(s=3,a=(1,1,1)\) 就有 \(w(1,2)+w(2,3)<w(1,3)+w(2,2)\)。
考慮直接欽定最後有 \(x\) 個區間 \([l_1,r_1],[l_2,r_2],\cdots,[l_x,r_x]\),每個區間的和都 \(\ge s\)。那麼為了有 \(k\) 段,只需要剩下的數的個數 \(\ge k-x\)。考慮設 \(f(x)\) 表示選 \(x\) 個和 \(\ge s\) 的不交區間,其最小的區間總長是多少。那麼 \(f\) 就是凸的了。可以感性理解為隨著選取的區間越來越多,\(f\) 增長的也會越來越快,因為會更難選取新的區間。嚴謹的證明可以在官方題解中找到。
既然是凸的那麼就都好辦了,我們要找到最大的 \(x\) 使得 \(n-f(x)\ge k-x\),也就是 \(f(x)-x\le n-k\)。顯然 \(f(x)-x\) 也是凸的,我們考慮直接二分斜率,找到縱座標 \(n-k\) 所在的線段,然後就可以 \(O(1)\) 計算出其橫座標。算一個 \(f(x)-kx\) 的切點顯然也可以做到 \(O(N)\)。綜上,總複雜度 \(O(N\log N)\)。
HDU6566
我草,好像假了,爆了
有人教我一下嗎???
2024.4.4
\(100+10+100=210\)。登頂了
A
顯然可以 \(O(\log N)\) 算一個字首 \(i\) 給 \(k\) 個數取反的答案,然後第 \(i\) 行的最優解 \(k_i\) 關於 \(i\) 單調,於是使用你喜歡的決策單調性處理手法即可。複雜度 \(O(N\log^2N)\)。
B
C
首先 \(X=0\) 好做,考慮 \(X\neq 0\),把極長的連續 \(0,X\) 段縮到一起,然後考慮 DP 每次加進來一段,只需要算一段的答案。嗯這個我找規律強行給他爆了,感覺實際推起來比較繁瑣。大概是利用字首 xor 此時只會是 \(0,X\),然後做一些分討。
然後轉移容易最佳化,做到 \(O(N)\)。
2024.4.5
\(47+71+40=158\),過了 \(0\) 題/開心
T3 就剩一個 case 就寫完了,那個 case 寫了個亂搞,本來能過 \(2\times 10^5\) 的,結果亂搞閾值開錯了直接掛飛了
A
那看到這個就想到容斥嘛,欽定集合 \(S\) 內部為若干個環,偶環造成 \(-1\) 貢獻,奇環造成 \(1\) 的貢獻,外面的點造成 \(\text{outdeg}\) 的貢獻表示隨便選出邊。然後我場上覺得這沒辦法最佳化呀?所以寫了列舉 \(S\),列舉排列算這東西的指數及做法。
實際上 \((-1)^{\#\text{even cycles}}=(-1)^{\#\text{inv}}\),所以這就是行列式。為了處理外面的點,給每個點多加 \(\text{outdeg}\) 個自環,這樣如果一個點選了新加的自環就表示他沒有被欽定在一個我們要求的奇環或者偶環裡。
這也就自然是題解說的 \(ans=\text{det}(D+G)\)。
B
看完就猜只需要 \(ab,cd\) 各自不相鄰就行,然後很容易得到 \(O(n)\) DP,也容易最佳化到 \(O(m^3\log n)\)。後面是 poly,跑一下 BM 得到答案的線性遞推然後 Bostan-Mori 即可。這裡 Bostan-Mori 的多項式乘法可以暴力 \(O(m^2)\) 做,但是我既不會 BM 也不會 Bostan-Mori 哈哈哈
感覺純爛題,爛完了
C
你就硬分類討論,\(k=1\) 好做,\(k=2\) 如果不交的話也好做,相交的話一定在笛卡爾樹上成祖孫關係,考慮如果選了 \((u,v)\) 其中 \(u\) 是 \(v\) 的祖先,其貢獻為 \(-len_v\times h_u+len_u\times h_u+len_v\times h_v\),在祖先處統計,李超樹合併維護 \((-len,len\times h)\) 的這些直線即可。
考慮 \(k=3\),三個互相不交的情況 DP 即可,如果可以分成兩個不交的部分也好做,然後如果三個形如 \(u,v,w\) 其中 \(u,v,w\) 依次為祖孫關係就只需要把 \(k=2\) 的再做一遍。
唯一難的情況是選一個祖先 \(u\),然後選兩個 \(v,w\) 滿足 \(v,w\) 互不為祖孫關係,造成的貢獻為
我們考慮放寬限制,發現當 \(u\) 不為 \(v,w\) 的祖先時,這個東西不會算的更大。考慮對 \(u\) 不做任何限制,只欽定 \(v,w\) 不交。那麼我們需要對一個 \((-len_i,len_i\times h_i)\) 這樣的東西求一下凸包,然後和自己做閔可夫斯基和。但還有一個不交的限制,這個該怎麼做呢
考慮建一個線段樹,每個子樹變成一個區間 \([l,r]\),考慮兩個不交區間 \([l_1,r_1],[l_2,r_2]\),不妨設 \(r_1<l_2\),我們在 \(\text{LCA}(r_1,l_2)\) 處統計這個貢獻。嗯然後大概你就很會了對吧。
具體來說,我們對每個線段樹節點維護兩個凸包 \(L,R\),然後對每個區間 \([l,r]\),我們在 \(l\) 的所有祖先的 \(L\) 凸包裡面插入這個點,\(r\) 的所有祖先的 \(R\) 凸包裡面插入這個點,然後我們對每個線段樹節點,把他左兒子的 \(R\) 凸包和右兒子的 \(L\) 凸包做閔可夫斯基和,把得到的這些點放到總的點集裡面,最後再對總的點集求一遍凸包。求出這個凸包之後,再列舉 \(u\) 計算即可。
綜上,總複雜度 \(O(N\log N)\)。
2024.4.6
\(100+100+65=265\),小小登頂了一波
A
後面那一坨就是 \(\binom{2k+1}{k}\)。證明考慮我們有 \(2k+1\) 個數,現在需要選出 \(k\) 個。我們把 \((2i-1,2i)\) 分成一組,這樣會分出來 \(k\) 組,和剩下的一個 \(2k+1\)。我們列舉有 \(m\) 組恰好選中了一個元素,方案數是 \(\binom{k}{m}2^m\),表示先選 \(m\) 組,然後在每一組裡面決策選哪個。那麼根據 \(k-m\) 的奇偶性可以唯一確定 \(2k+1\) 是否被選中,同時剩下的 \(k-m\) 組一定全選了 \(\lfloor \frac{k-m}{2}\rfloor\) 組,於是方案數就只需要再乘一個組合數。
於是容易 \(O(n)\) 預處理 \(O(1)\) 回答詢問。
B
容易想到 \(O(n^2)\) DP:\(dp_{i,j}\) 表示目前剛拿出來第 \(i\) 個球,恰好 \(j\) 個球被拿了恰好一次的機率。其中 \(dp_{0,0}=1\),對於 \(i\ge 1\) 我們欽定 \(1\le j\le i\)。轉移形如:
這個可能沒有最佳化空間,常規的套路是直接維護下降冪 \(f_{i,j}=\sum dp_{i,k}\binom{k}{j}\),那麼直接根據組合意義就可以推出 \(f\) 的轉移式,這裡略過。注意到 \(f\) 的轉移只有 \((i,j)\to (i+1,j/j+1)\),而我們用到的只是 \(f_{n,0\cdots,m}\),因此只對這些位置 DP 即可做到 \(O(nm)\)。
C
EZEC 雪的魔法。
首先線性規劃對偶,然後轉成一個平面圖最短路題,類似 PA2021 Desant 2 地做即可。
2024.4.7
eps+eps+eps,具體得分忘了,好像三個題加起來勉強拼上了 \(100\) 出頭
又是會 0 題的一天呢/開心
A
轉化成二分圖匹配之後考慮 Hall 定理,但一個不合法方案可能會有多個集合 \(S\) 滿足 \(|N(S)|<|S|\)。考慮對每種不合法方案選取 \(S\) 的代表元,使得代表元唯一,並對代表元計數。這裡 \(N(S)\) 表示左部點 \(S\) 在右側的相鄰點集。
我們選取所有 \(|S|>|N(S)|\) 的集合 \(S\) 中 \(|S|-|N(S)|\) 最大的,如果有多個,則選取 \(|S|\) 最小的。那麼如果存在兩個最優的集合 \(S\neq T\) 使得 \(|S|-|N(S)|=|T|-|N(T)|>0\),則由於 \(|S\cap T|<|S|\),必有 \(|S\cap T|-|N(S\cap T)|<|S|-|N(S)|\)。於是
這就匯出了矛盾。第一個不等號是大於等於,是因為 \(|N(S\cap T)|\le |N(S)\cap N(T)|\)(如果一個點被算到了左邊,那麼顯然在右邊也會被算進去),而 \(N(S\cup T)=N(S)\cup N(T)\),於是有 \(|N(S\cup T)|+|N(S\cap T)|\le |N(S)\cap N(T)|+|N(S)\cup N(T)|=|N(S)|+|N(T)|\)。
現在考慮計算 \(dp(S,S_1)\) 表示左部點集合 \(S\) 和右部點集合 \(S_1\),只考慮這些點之間的連邊,不存在 \(T\subseteq S,T_1\subseteq S_1\) 滿足 \((T,T_1)\) 比 \((S,S_1)\) 優的機率。考慮容斥,首先欽定 \(N(S)=S_1\),然後減掉實際的最優不合法子集為 \((T,T_1)\neq (S,S_1)\) 的機率。
考慮這需要什麼條件,首先我們欽定恰好有 \(N(T)=T_1\),然後需要 \((S-T,S_1-T_1)\) 合法,否則取 \(C\subseteq S-T,C_1\subseteq S_1-T_1\) 且 \(|C|>|C_1|\) 就有 \((T\cup C,T_1\cup C_1)\) 更優;進一步,由於 \((S-T,S_1-T_1)\) 合法,任取 \(D\subseteq T,C\subseteq S-T\),其 \(D\cup C\) 都不可能比 \(T\) 更優。
綜上我們完成了轉移,複雜度 \(O(3^{2n})\)。
實際上,考慮加點的過程中動態維護二分圖匹配,具體來說我們依次加入左部點,維護每個右部點集合 \(S\) 能否和當前已加入的點形成完美匹配,並動態更新即可。容易發現集合個數不會超過 \(\binom{n}{\lfloor n/2\rfloor}\),於是複雜度有很鬆的上界 \(2^{\binom{n}{n/2}}\);實現程式碼後可以發現實際狀態數在 \(n\le 7\) 時只有 \(W=40000\) 左右,於是可以在 \(O(n2^nW)\) 的時間複雜度內解決本題。
B
考慮怎麼判合法,首先有球的位置肯定得是最靠下的若干個位置,也就是說沒有球的位置集合要麼為空,要麼是包含根的一個連通塊。
我們考慮一個點落進來若干個球,如果欽定了他們的順序,以及他們往哪個兒子裡面走,那麼其實最終落到哪些點上就是唯一確定的,而且不同的順序一定也會得到不同的結果。
唉,這個題還是很神秘,我大概會編一個 dp 了,但是這個還是很神秘
題
給 \(m,k,b\),求第 \(m\) 大的,是 \(10^k-1\) 的倍數,且十進位制表示下沒有數碼 \(b\) 的數。
\(m\le 10^{16},k\le 16\)
逐位確定答案,每次計數一下後面的方案數。我們都知道 \(\bmod (x^k-1)\) 就是 \(f_i\to f_{i\bmod k}\) 所以先列舉結果是 \((10^k-1)\times p\) 其中 \(p\) 大概不會超過 \(20\),然後數位 DP,每次把 \(\bmod k\) 相同位的都一起填了,模擬從低到高進位就行。
題題
給 \(m,k,b\),求第 \(m\) 大的 \(x\),滿足 \(x\) 十進位制下數位沒有 \(a\),\((10^k-1)x\) 的十進位制表示下沒有數碼 \(b\)。
\(m\le 10^{16},k\le 16\)
考慮依次填 \(x\),那麼 \(10^kx-x\) 可能會有 \(16\) 位要決策是否往後借一位,\(2^{16}\) 列舉之即可。
2024.4.8
\(100+100+100=300\)。?
今天過了 3 題/難過
A
離線後變成若干次查詢 \(B[s,t]\) 在 \(A[l,r]\) 中的出現次數,用你喜歡的字串資料結構維護即可。
例如可以使用 SAM 變成二維數點,容易在 \(O(N\log N)\) 時間內解決。
B
這個問題的研究物件是所有點分樹。
先嚐試去掉 \(k\) 的限制,計數合法的點分樹個數。考慮使用一些合法解來構造更多的合法解,思考怎麼把兩個子樹的點分樹合併成一個大的點分樹。
設我們現在有 \((u,v)\) 這條邊,\(u\) 左邊的連通塊構成一個點分樹,\(v\) 右邊的連通塊構成一個點分樹。
那麼要得到兩個連通塊並起來的點分樹,首先我們需要選擇全域性的根節點,它一定是兩邊的根節點之一。例如我們選擇了 \(u\) 這一側的點分樹根節點作為全域性點分樹的根節點,那麼刪去這個根節點後分成若干連通塊,不包含 \(u\) 的聯通塊就沒有用了,剩下的部分是 \(u\) 那邊的點分樹和 \(v\) 那邊的點分樹接著合併。
於是我們發現實際上我們可以任意歸併 \(u\) 到其點分樹根節點上的點,和 \(v\) 到其點分樹根節點上的點。那麼對於沒有 \(k\) 的限制的部分,只需要記錄這裡有多少個點即可。
嚴格來說,我們還需要證明這個過程的確能得到所有點分樹。這部分可以參考 command_block 的部落格。
回到本題,注意到 \(k\) 較小,考慮直接暴力把這一條鏈上的點欽定的標號值 \(p_1,p_2,\cdots,p_x\) 壓進狀態,注意到它們的順序一定是從根到 \(u\) 依次遞增,且 \(u\) 一定是最後一個,因此只需要儲存集合,狀態數為 \(O(n2^k)\)。
轉移時,假設要合併 \(f(u,S),f(v,T)\),由於最終 \(S,T\) 這些點都會到一條鏈上,因此他們的標號值一定互不相同;由於我們欽定了標號值,因此歸併順序是唯一的。在歸併之後,由於狀態的定義是隻記錄 \(u\) 到根鏈上的點,因此我們需要把 \(S+T\) 中 \(>\max S\) 中的元素刪掉。暴力進行轉移,即可得到 \(O(n3^k)\) 的做法。
容易使用子集卷積最佳化到 \(O(nk^22^k)\),但 \(k\) 只有 \(17\),我感覺其實跑不過 \(n3^k\) 呀......
無語了,std 寫的是卡常的 \(O(n3^k)\)
C
相當於維護兩個圖 \(G,H\),要求支援在 \(G\) 中插入一條邊,刪除一條邊,查詢多少個點對 \((i,j)\) 滿足 \(i,j\) 在 \(G\) 中連通或者在 \(H\) 中連通。
對每個 \(i\) 維護 \(a_i,b_i\) 表示 \(i\) 在 \(F,G\) 中所在的連通塊編號,那麼啟發式合併維護一下,容易發現只需要維護 \(O(n\log n)\) 次單點修改 \(a,b\),查詢多少對 \((i,j)\) 滿足 \(a_i=a_j\) 或 \(b_i=b_j\)。簡單開個桶維護即可。
我的程式碼使用了 map,複雜度為 \(O(n\log^2n)\)。
2024.4.9
\(100+100+40=240\)。今天過了 2 題/難過
A
注意到一般情況是 4-SAT,是 NP-Hard 問題,考慮分析約束的性質。
約束形如 \(4\Rightarrow (3\iff 2) \Rightarrow 1\),發現 \(1,4\) 相對而言比較容易確定,而且對約束的影響也不大。考慮貪心地把顏色染為 \(1\) 和 \(4\),然後對剩下的跑二分圖染色。
考慮什麼時候可以確定一個 \(i\) 一定不能染成 \(4\),把 \(a\) 剋制 \(b\) 看做 \(a>b\),不剋制看做 \(a\le b\),發現相當於存在 \(x\) 而且能確定 \(x>i\)。那麼我們先把那些被直接剋制的確定為 \(\neq 4\),然後如果 \(x\neq 4,x\ge y\) 就把 \(y\) 也確定為 \(\neq 4\)。同理也可以確定哪些一定 \(\neq 1\)。然後我們貪心把能填成 \(1,4\) 的都填成 \(1,4\) 即可。
那麼剩下的必須是 \(2,3\),跑二分圖染色即可。
B
首先 \(p,q\) 都是排列,這意味著我們實際上只需要考察 \(1,2,\cdots,n\) 能變成哪些排列。
其實這個我很熟,之前我還出過一個類似的題......直接猜出來除去 \(m\ge n-1\) 的 corner case,其餘情況當 \(2\mid m\) 時可以得到所有逆序對個數不變的排列;\(2\nmid m\) 的時候可以得到所有排列。實現暴力後觀察,發現的確如此。
接下來我猜只需要使用 \(len=m+1\) 的操作就夠用了,實際上暴力表明確實如此,但是我好像沒能構造出來。於是我加上了 \(len=m+2\) 的操作,發現就簡單了不少。
先考慮 \(2\nmid m\) 的情形,我們考慮在 \(n\) 次操作內完成一次 swap 相鄰兩項。考慮我們要交換 \(a,b\),有如下的方法:(其中每次用中括號框起來的是操作的區間)
- \([a,b,x_1,\cdots,x_m] \Rightarrow x_1,\cdots,x_m,a,b\)
- \([x_1,\cdots,x_m,a],b\Rightarrow a,x_1,\cdots,x_m,b\)
接下來我們操作 \(\frac{m-1}{2}\) 次整個區間,每次會把 \(b\) 往前移動兩個位置,最後就變成 \(b,a,x_1,\cdots,x_m\)。由於 \(2\nmid m\),因此的確會恰好移動到這個狀態。
問題是 \(a,b\) 後面可能不足 \(m\) 個元素。std 的解決方式是,直接任取一個和 \(m\) 互質的長度 \(len\),滿足 \(a,b\) 在區間 \([1,len]\) 中,然後不斷 shift \([1,len]\) 把 \(a,b\) 換到開頭。
我的方法是對最後 \(m+2\) 個元素 shift,直到 \(a,b\) 後面出現了 \(\ge m-1\) 個元素。這種情況根據 \(a,b\) 後面初始元素個數的奇偶性還可能會出現最終得到 \(y,a,b,x_1,\cdots,x_{m-1}\) 的情況。對於這個,我們的方案是:
- \([y,a,b,x_1,\cdots,x_{m-1}]\Rightarrow b,x_1,\cdots,x_{m-1},y,a\)
- \([b,x_1,\cdots,x_{m-1},y],a\Rightarrow x_1,\cdots,x_{m-1},y,b,a\)
然後還是對整個區間往前 shift \(\frac{m-1}{2}\) 次即可。
現在考慮 \(2\mid m\) 的情形。考慮構造出 \(n\) 次操作內 \(a,b,c\to c,a,b\) 的方案,然後依次歸位 \(1,2,\cdots,n-2\)(操作 \([i-1,i+1]\) 即可讓 \(i\) 向前移動一位,\(i=n\) 就操作 \([i-2,i]\)),由於逆序對個數奇偶性不變,因此 \(n-1,n\) 此時一定已經歸位。具體方案是:
- \([a,b,c,x_1,\cdots,x_{m-1}]\Rightarrow c,x_1,\cdots,x_{m-1},a,b\)
- \(c,[x_1,\cdots,x_{m-1},a,b]\Rightarrow c,b,x_1,\cdots,x_{m-1},a\)
- \(c,[b,x_1,\cdots,x_{m-1},a]\Rightarrow c,a,b,x_1,\cdots,x_{m-1}\)
然後同理按照我的處理方法也會遇到 \(y,a,b,c,x_1,\cdots,x_{m-2}\) 的情況,類似上面也可以做。
感覺這題,純依託,我從九點多做到十二點多,根本沒時間做 T3/ng
C
連通塊個數為 \(k\) 相當於實際加入了 \(n-k\) 條邊。下面令 \(k\leftarrow n-k\)。
顯然有 \(O(n^2)\) DP:\(f_{i,j}\) 表示加了 \(i\) 條邊,現在還有 \(j\) 個孤立點。
考慮容斥,欽定若干邊必須被加入,考慮算此時的方案數。
我們發現這裡如果想要去算方案數的話,可能最後需要除掉 \(\binom{n}{2}!\),而這些我們都不太能計算。不過打表發現 \(k=1\) 的方案數是 \(\binom{n}{2}!\times \frac{2^{n-2}}{Cat_n}\),其中 \(Cat_n=\frac{1}{n+1}\binom{2n}{n}\) 為卡特蘭數,這表明 \(\binom{n}{2}!\) 大機率會被約掉,我們可以嘗試去推一下。
這相當於對這 \(\binom{n}{2}\) 條邊的順序有一些要求,如果一條邊的兩個端點連線的都是孤立點,那麼這條邊的順序我們沒有做要求;如果兩條邊連線的都是被我們欽定的邊的端點,那麼首先不能成環,它需要在其中靠後加入的那個連通塊加入的時刻之前被加入。
那麼在確定真的連了哪些邊之後,會得到一個森林,我們先嚐試對一個森林該怎麼算他的機率。首先顯然最終的圖沒有孤立點,於是每個連通塊至少有一條邊。在確定這個連通塊第一條加入的邊之後,剩下的機率相當於一棵樹的拓撲序。這個對每個子樹是獨立的,於是可以得到其機率是
大概是這樣的形式,\(P\) 是所有連通塊的集合,\(T\) 是一個連通塊(一棵樹),\((u,v)\) 是第一條加入的邊,\(siz_x\) 是此時 \(x\) 在 \(u\) 另一側的子樹 size。
這個也不是很對,我們考慮直接去欽定是哪些邊作為了這個連通塊的第一條邊,這個時候發現,你欽定的這東西的個數,就是連通塊的個數。那麼欽定了 \(x\) 條這種邊,首先會有 \(\binom{n}{2x}(2x-1)!!\) 種方案,接下來就讓他們是 \((1,2),(3,4),\cdots,(2x-1,2x)\),然後計算這些邊真的作為初始邊的方案數。
那我們先不考慮容斥啥的事情,就讓他們真的是所有的初始邊,來試著算一下這個式子。那麼剩下的所有點都得掛到這些邊上,然後初始邊之間是不能有連邊的。發現相當於對於其他的每條邊,為了不讓這個初始邊被其他邊連過來,那麼它的加入時刻不能比它相鄰的初始邊早。
給初始邊欽定順序並插入到操作序列,有 \(x!\) 種方案;接下來考慮最後一個被加入的初始邊,所有邊只要和他相鄰,就必須在它之後被加入。這樣的邊有 \(2(n-2)\) 條;然後不和最後一條邊相鄰,但和倒數第二條邊相鄰的邊,需要在倒數第二條邊那裡被加入。這樣的邊有 \(2(n-3)\) 條。
於是最終的順序連成樹形結構,其子樹的 size 分別是 \(2n-3,4n-10,\cdots\)。
於是這個式子大概長成
但這個時候還有 \(\binom{n-2x}{2}\) 條邊沒有被欽定,而它們可能產生新的初始邊。容斥即可。
最終我們的答案就是
KOI TST 2024
Day1 A
對於長為 \(m\) 的序列 \(x\),認為它是好的當且僅當 \(m\ge 2\),且 \(\max(x_1,x_m)<\min(x_2,x_3,\cdots,x_{m-1})\)。
考慮序列長為 \(n\) 的 \(a\),你可以進行任意次操作,每次可以選擇一個區間 \([l,r]\) 滿足 \(a_l,a_{l+1},\cdots,a_r\) 這個序列是好的,然後刪除 \(a_{l+1}\cdots a_{r-1}\),接下來序列會變成 \(a_1,a_2,\cdots,a_{l-1},a_l,a_r,a_{r+1},\cdots,a_n\)。你希望最大化最終序列的所有元素的平均值。設 \(f(a)\) 為上述問題的答案。
給定長為 \(N\) 的序列 \(A\),有 \(Q\) 次詢問,每次給出 \(l,r\),你需要輸出 \(f(A[l\cdots r])\) 的值。具體來說,設答案化為最簡分數後為 \(\frac{x}{y}\),你需要輸出一行兩個正整數 \(x,y\) 表示答案。
保證每次詢問給出的 \(l,r\) 滿足:\(A[l\cdots r]\) 是一個好的序列。
\(2\le N\le 3\times 10^5,1\le Q\le 6\times 10^5,1\le A_i\le 10^9,1\le l<r\le N\)。5s 1024MB
我真無語了,我第一次翻譯的時候少翻譯了一個條件(\(A[l\cdots r]\) 是好的序列),做了一萬年都不會。。
考慮一次詢問怎麼算答案,二分答案 \(mid\),每個數 \(a_i\leftarrow a_i-mid\) 後只需要總和 \(\ge 0\)。為了輸出精確分數,只需要多記錄一下最優解選了幾個數。設 \(f_i\) 表示前 \(i\) 個數的最大總和,\(i\) 一定不會被刪除,考慮是否有一次右端點為 \(i\) 的刪除,可以轉移到 \(\max_{\text{valid}(j,i)}f_j+a_i\),其中 \(\text{valid}(l,r)=[\max(a_l,a_r)<\min(a_{l+1}\cdots a_{r-1})]\)。
設 \(p_i,q_i\) 分別表示左右兩側第一個 \(<a_i\) 的位置,那麼 \(\text{valid}(l,r)=[q_l\ge r\land p_r\le l]\)。可以用資料結構最佳化。
實際上,考慮從前往後維護單調棧,把區間按照 \(a_l>a_r\) 和 \(a_l\le a_r\) 分類。如果 \([j,i]\) 合法且 \(a_j>a_i\),那麼 \(j\) 一定是 \([1,i-1]\) 的一個嚴格字尾最小值。於是我們維護單調棧,那麼以 \(i\) 為右端點的所有合法區間就是插入 \(a_i\) 時彈出的那些 \(j\) 組成的區間。那麼這樣的區間個數不超過 \(N\),於是總的合法的區間數量不會超過 \(2N\) 個。
於是現在我們可以對單次詢問的情況做到 \(O(N\log V)\)。
注意到只需要處理所有合法區間的答案,而它們要麼不交要麼互相包含。於是可以對合法區間建出一棵樹,設 \(f(u,j)\) 表示只考慮 \(u\) 代表的區間,保留 \(j\) 個數所能達到的最大總和。那麼首先有 \(f(u,2)\leftarrow a_{l_u}+a_{r_u}\),然後我們需要對 \(u\) 的若干兒子做 max+ 卷積,最後整體加上那些一定存在的數,也就是做一個整體偏移。
由於我們只關心 \(\frac{f(u,j)}{j}\) 的 max,考慮有三個點 \(A,B,C\),座標分別為 \((x_A,y_A),(x_B,y_B),(x_C,y_C)\),不妨設 \(x_A<x_B<x_C\),如果這三個點不形成上凸,那麼可以證明 \(A,C\) 至少一個比 \(B\) 優。
於是我們只需要維護上凸殼上的點,合併時做 max 卷積直接維護閔可夫斯基和即可。這裡為了能算出每個點的答案,可能不能簡單地只維護凸包上的每條邊,需要用平衡樹維護整個凸殼上面的點來支援快速算字首和的操作。
時間複雜度 \(O(N\log^2N+Q)\)。
https://qoj.ac/submission/394318
Day1 B
給定序列 \(a\),每次選擇一個 \(i\) 滿足 \(1\le i\le |a|-1\),且 \(a_i=a_{i+1}\),然後刪除 \(a_i,a_{i+1}\),並在同樣的位置插入 \(a_i+1\)。例如 \([2,1,1,3,2]\) 可以變成 \([2,2,3,2]\),方法是選擇 \(i=2\)。
你可以對序列進行任意次操作,例如上面的序列可以接著變成 \([3,3,2]\) 再變成 \([4,2]\)。你希望最大化最終序列中所有數的最大值。定義上述問題的答案為 \(f(a)\)。
給定長為 \(N\) 的序列 \(A\),有 \(Q\) 次操作,每次操作是以下二者之一:
1 l r
:輸出 \(f(A[l\cdots r])\) 的值。2 p v
:令 \(A_p\leftarrow v\)。\(1\le N,Q\le 10^5,1\le A_i\le 10\);對於
1
操作,\(1\le v\le 10\)。
考慮一個 \(f\) 怎麼算,把序列劃分為相同數的極長連續段 \((x_1,c_1),(x_2,c_2),\cdots,(x_k,c_k)\),其中 \(x_i\) 是第 \(i\) 段的值,\(c_i\) 是第 \(i\) 段的元素個數。每次我們找到序列中的所有最小值,顯然把它們縮起來一定不劣。
分類討論一下,如果 \(c_i\) 是偶數,那麼直接縮成 \((x_i+1,\frac{c_i}{2})\);否則這個 \((x_i,c_i)\) 左右一定不可能發生合併了,它們互相獨立,於是我們可以把 \((x_i,c_i)\to (x_i+1,\frac{c_i-1}{2}),(-1,1),(x_i+1,\frac{c_i-1}{2})\),這裡 \(-1\) 表示一個分隔符,它的左右互相獨立。
這樣每次縮完 \(a\) 中的 min(這個 min 不算 \(-1\))都至少 \(+1\),於是最多進行 \(O(\max a_i)\) 輪所有數就都相等了。這樣我們可以在 \(O(n\max a_i)\) 的時間內算出一個 \(f\)。
考慮區間詢問怎麼做,事實上我們發現只要 \(x_i<\min(x_{i-1},x_{i+1})\),我們就一定必須得把 \((x_i,y_i)\) 化簡一下。於是考慮線段樹維護每個區間這樣縮完之後變成什麼樣子即可。可以發現這樣一直縮下去最終每個區間只會剩下左右兩側的各 \(O(A_i)\) 個段,以及中間可能被阻斷的若干段。中間那些段顯然不會再造成貢獻了,只需要記錄他們的 max;合併的時候處理一下是否出現新的段即可。
時間複雜度 \(O(A(N+Q\log N))\)。我偷懶寫了一個 \(O(A^2(N+Q\log N))\) 的,qoj 神機給我跑過了/jy
https://qoj.ac/submission/392764
Day1 C
給定一棵 \(N\) 個點的樹,第 \(i\) 條邊連線 \(A_i,B_i\) 兩個點,長度為 \(C_i\) 米。
現在有 \(Q\) 次詢問,每次會給出兩個點 \(x,y\) 和兩個速度上限 \(v_x,v_y\),有一個警察和一個小偷,警察一開始在 \(x\) 點,小偷一開始在 \(y\) 點(保證 \(x\neq y\)),警察的速度上限為 \(v_x\) 米每秒,小偷的速度上限為 \(v_y\) 米每秒,在每一時刻他們都可以任意移動(可以以任意不超過速度上限的速度移動,當然也可以不動),而且可以不消耗時間地改變方向。
如果某一時刻警察和小偷在同一個位置就認為小偷被抓獲(這個位置可以在一條邊的中間)。
小偷希望最大化他被抓獲的時間,警察希望最小化這個時間。兩人每時每刻都知道對方當前的位置和速度,你需要求出如果兩人都採取最優策略,小偷會在什麼時候被抓獲。
可以證明這個時間一定是有理數,設它化為最簡分數後為 \(\frac{x}{y}\),你需要輸出一行兩個正整數 \(x,y\)。
\(1\le N,Q\le 10^5,1\le C_i\le 10^6,1\le v_x,v_y\le 10^6\),輸入的數都是正整數。
這個題是不是糖了?考慮小偷可能會先往警察的方向走若干秒,然後從某個地方開始折返往外跑,且往回走的過程中不能被警察抓住。二分出這個分界點,那麼相當於要求這個點一側距離警察最遠的一個點。分類討論一下即可。
複雜度感覺一個 log 就行。
AtCoder mujin pc
2017 D
給定一棵 \(n\) 個節點的樹,現在你需要給每條邊定向,定完方向後,設 \(d(u,v)\) 表示:在這張有向圖上,想要使 \(u\) 能夠到達 \(v\),至少需要翻轉幾條邊的方向。這個定向方案的代價是 \(\max_{u,v}d(u,v)\)。
你希望最小化代價。在此之上,你希望求出在 \(2^{n-1}\) 種方案中,有多少種方案能夠最小化這個代價。
\(1\le n\le 3000\),答案對 \(998244353\) 取模。
首先,有簡單 \(O(n^3)\) DP。
設直徑長度為 \(D\),那麼最小代價是 \(\lceil D/2\rceil\)。下面分類討論:
- 直徑長度為偶數
找到直徑中間的那個點,以這個點為根建樹,稱父親指向兒子的為正向邊,兒子指向父親的為反向邊,那麼每個深度恰為 \(\frac{D}{2}\) 的點到根的路徑上,正向邊和反向邊個數之差都相等。考慮給每個點一個標號 \(w\),他滿足如果 \((u,v)\) 這條邊定向為 \(u\to v\) 則 \(w_v=w_u+1\);否則 \(w_v=w_u-1\)。那麼所有深度恰為 \(\frac{D}{2}\) 的點的 \(w\) 值都相同,不妨欽定這些點的 \(w=0\),那麼此時定向方案與合法的 \(w\) 的方案形成雙射。
設 \(r\) 為直徑中點,可以發現,此時一個方案合法,當且僅當對所有 \(u\),都有 \(|w_u|\le \frac{D}{2}-\text{dist}(u,r)\)。首先必要性是顯然的,然後注意到 \(d(u,v)\le \frac{w_u-w_v+\text{dist}(u,v)}{2}\)(當 \(\text{LCA}(u,v)=r\) 時取等號),於是
於是充分性得證。於是我們直接 DP 即可,複雜度 \(O(n^2)\)。
- 直徑長度為奇數
找到直徑中間的那條邊 \((r_1,r_2)\),設 \(r_1\) 一側的點集為 \(S_1\),\(r_2\) 一側的點集為 \(S_2\),類似地給每個點標號 \(w\),和上述情況類似,只不過這次根據中間那條邊的朝向,可能會有某一側的點集的約束需要額外 \(-1\) 也就是更嚴一點。
類似地也可以做到 \(O(n^2)\)。
2018 H
考慮 \(H\times W\) 的網格,現在你需要給每個格子黑白染色。定義一種染色方案合法,當且僅當能夠用 \(1\times 2\) 的紙條不重疊且不超出網格邊界地恰好覆蓋所有白色格子,恰好不覆蓋所有黑色格子。
求合法染色方案數對 \(998244353\) 取模的值。\(1\le H\le 5,1\le W\le 10^9\)。
這個題是不是糖了?考慮怎麼判合法,發現需要記錄最後一行還沒填入的白色格子 \(S\)。
那麼再套一層就是把這些全壓進來。看上去狀態數有 \(2^{2^H}\) 個,但是毛估估一下就不是很多。
這裡直接搜大概會得到 \(H=5,6,7,8\) 狀態數分別為 \(91,318,1223,5085\);但我們注意到只需要考慮當前最後一行已經填到沒有相鄰空位的那些狀態,這樣可以大大減少狀態數,分別為 \(26,61,169,520\)。
搬雲鬥了
Singapore NOI 2024
D
有一個 \(1,2,\cdots,n\) 的排列 \(p\)。你並不知道這個排列 \(p\) 是什麼。
現在給出 \(m\) 條資訊 \(x,y\),表示可以確定 \(p_x<p_y\)。
對每個 \(i=1,2,\cdots,n\),輸出最小的 \(k\) 滿足:可以用前 \(k\) 條資訊推出 \(p_i\) 的值。
如果不存在這樣的 \(k\),輸出 \(-1\)。保證存在至少一個排列符合所有約束。
\(2\le n\le 2\times 10^5,1\le m\le 8\times 10^5\)。
首先,我們在最終的圖中找到一個拓撲序,然後對這個排列做一下置換。下面我們欽定每次給出的 \(x,y\) 都滿足 \(x<y\);一個數 \(x\) 當前能被確定,當且僅當它能到達 \(x-1\) 個點,且有 \(n-x\) 個點能到達它。
我們考慮 \(x-1\),發現他必須得能從 \(x\) 直接到達;進一步考慮 \(x-2\),發現它的入邊裡面至少得有 \(x-1\) 或 \(x\)。
依此類推,我們可以發現,如果設 \(a_i\) 表示 \(i\) 的入邊中編號最小的點,那麼 \(x\) 能到達 \(1,2,\cdots,x-1\),當且僅當對所有的 \(i=1,2,\cdots,x-1\),都有 \(a_i\le x\)。同理設 \(b_i\) 表示 \(i\) 的出邊中編號最大的點,那麼還需要對所有的 \(i>x\),都有 \(b_i\ge x\)。
每次修改對 \(a,b\) 的影響是 \(O(1)\) 的,簡單用線段樹維護下就行。時間複雜度 \(O((n+m)\log n)\)。
E
有一個無限大的二維平面,你一開始在 \((0,0)\)。你每一秒可以向上下左右移動 \(1\) 的距離,也就是說這一秒如果你在 \((x,y)\),那麼下一秒你可以走到 \((x-1,y),(x+1,y),(x,y-1),(x,y+1)\) 中的一個。
給定 \(n\) 個矩形,第 \(i\) 個矩形可以用 \(a_i,b_i,c_i,d_i\) 表示,意思是所有滿足 \(a_i\le x\le b_i,c_i\le y\le d_i\) 的點都被移除了,不可以經過。這些矩形可能會互相重疊。
設 \(d(x,y)\) 表示走到 \((x,y)\) 所需的最短時間。如果走不到 \((x,y)\),則 \(d(x,y)=-1\)。特別地,\(d(0,0)=0\)。
現在有 \(q\) 次詢問,詢問有兩種:
1 x y
:輸出 \(d(x,y)\) 的值。2 m
:輸出有多少個 \((x,y)\) 滿足 \(0\le d(x,y)\le m\)。\(1\le n\le 400,1\le q\le 2\times 10^5,-10^9\le a_i\le b_i\le 10^9,-10^9\le c_i\le d_i\le 10^9\)。
對於第 \(1\) 種詢問,\(-10^9\le x,y\le 10^9\);對於第二種詢問,\(1\le m\le 10^9\)。
保證 \((0,0)\) 不被任何矩形覆蓋;輸入的數都是整數。
題解看上去很恐怖。。。
Luogu9521
給定 \(n,m\) 和序列 \(a_1,a_2,\cdots,a_n,b_1,b_2,\cdots,b_m\),有一個 \(n\times m\) 的網格圖,每條邊有邊權,其中 \((i,j)\to (i,j+1)\) 邊權為 \(a_i\),\((i,j)\to (i+1,j)\) 邊權為 \(b_j\)。
現在要從 \((1,1)\) 走到 \((n,m)\),最小化邊權和。\(1\le n,m\le 10^5,1\le a_i,b_i\le 10^9\)。
考慮一個 \(L_a\times L_b\) 的矩形,橫著的兩條邊邊權上下分別為 \(a_1,a_2\),豎著的左右分別為 \(b_1,b_2\),那麼可以發現我們比的是 \(a_1\times L_a+b_2\times L_b\) 和 \(a_2\times L_a+b_1\times L_b\)。做差得到
也就是說,如果 \(a\) 那邊的斜率更大,那麼就應該先橫著走;否則就豎著走。
這也就是說,最優解中的每一條折線,都應該滿足,他先走的是斜率小的那一側。
此時有一個 \(O((n+m)\log (n+m))\) 的做法:每次找到全域性最大的差分位置,然後消掉所有不可能的拐點。這樣最後路徑只會剩下一條,用 std::set
維護即可。官方題解裡有詳細的圖解。
事實上,考慮三個點 \((i,a_i),(j,a_j),(k,a_k)\),如果他們不形成下凸,那麼 \(i,j\) 之間的斜率比 \(j,k\) 之間要小,也就是說如果我們某一步選擇了先走 \(i\to j\) 那麼一定會立刻走 \(j\to k\),於是我們可以直接把路徑縮成 \(i\to k\)。於是只需要求出 \(a,b\) 的下凸殼,每次走斜率小的一邊即可。複雜度 \(O(n+m)\)。
LuoguP5972
好像是我初二的時候提出的一個問題,當時 u 群有人說存在 \(O(n^23^{n/3})\) 做法,昨天晚上突然會做了!
考慮從前往後 DP,暴力是記錄 \(S\) 表示目前選擇的數的集合,這樣狀態數仍然是 \(O(2^n)\) 級別。
但我們注意到,設 \(i\) 後面的數分別為 \(x_1,x_2,\cdots,x_k\),我們只關心 \([1,x_1),(x_1,x_2),\cdots,(x_k,n]\) 這些每一段中選了多少個數。於是狀態數不會超過每段長度 \(+1\) 的乘積,由柯西不等式可以知道一定在段長相同時取到最值,直接看成連續的情況來分析,簡單求導可以得到最值在 \(e^{n/e}\),由於問題是離散的於是最值大約是 \(\max(2^{n/2},3^{n/3})\)。
於是直接 DP 就可以了。時間複雜度是 \(O(n^23^{n/3})\),使用 map
或許會被卡常,手寫雜湊表可以穩過。
LOJ3490
只會 \(O(n^3m+q)\) 左右的做法,紫砂了。
大概是把所有分段函式都求出來,之類的,每一段會形如一段平的或者斜率為 \(-1\) 的東西。
等會兒,打贏復活賽了,考慮怎麼算 \(s\to t\) 不能等待任何一天情況下的最短路,發現這個情況下,我們不妨欽定它就得被某條邊卡住,也就是在 \(C-L\) 時刻到達這裡,然後在 \(C\) 時刻離開。如果沒有被卡住,我們知道這段斜率是平的,那算出來的值也是對的。
然後再考慮等待至少一天的最短路,欽定那條第一次等待的邊,也是類似的。那麼首先我們算出每條邊 \(C\) 時刻以及 \(L\) 時刻離開之後到每個點的最短路,這部分跑 \(m\) 次 dij 有複雜度 \(O(m(n+m))\),然後再反著跑 dij,最後 \(q\) 次詢問只需要二分找字尾最小值即可,複雜度 \(O(n^2m+m^2+q\log n)\)。
首先,我們有 \(O(q(n^2+m))\) 的演算法,即每次跑一遍 dijkstra,同時記錄到每個點的最短路以及這個最短路對應的時刻。可以證明只要這樣就能得到最優解。
把路徑分成兩類:在一天內完成的,和至少有一次等待到下一天的。
對於在一天內完成的路徑,我們考慮找到其中限制最嚴(也就是經過這條邊的時間最接近他的限制時間)的一條邊 \((u,v,L,C)\),假設我們是從 \(s\) 走到 \(t\),起始時間為 \(A\),如果走到點 \(u\) 的時候時刻為 \(B\le C-L\),那麼我們知道這條邊的 \(C-L-B\) 是所有邊裡面最小的一個。
我們把起始時刻加上 \(C-L-B\),可以發現路徑仍然合法。於是有如下的演算法:列舉每條邊 \((u,v,L,C)\),計算 \(dis_x\) 表示想要從 \(x\) 走到 \(u\),滿足:
- 整個過程必須在一天內完成。
- 到達 \(u\) 時,當前時刻 \(\le C-L\)。
這種情況下所需的最小時間。這可以透過一遍 dijkstra 在 \(O(n^2+m)\) 的時間內算出,同時也可以算出 \(tim_x\) 表示如果要求能走這個最短路,\(x\) 的起始時間最晚是多少。再透過一遍 dijkstra 算出 \(to_y\) 表示從 \(v\) 到 \(y\),起始時間為 \(C\),所需的最少時間(這個過程同樣必須在一天內完成)。
算出這些之後,我們就可以計算 \((u,v,L,C)\) 這條邊對所有點對 \((x,y)\) 的貢獻,即對於起始時間 \(A\le tim_x\),都有一種 \(dis_x+to_y+L\) 的方案。
現在考慮跨越多天的路徑,注意到如果在某個城市 \(u\) 進行等待,一定是等待到第二天的 \(0\) 時刻,然後在 \(L\) 時刻出現在某條邊 \((u,v,L,C)\) 的終點 \(v\)。
於是類似地,我們列舉路徑上第一條進行等待的邊 \((u,v,L,C)\),同理算出 \(tim,dis,to\)(只不過此時從 \(v\) 開始走的時候,我們允許它跨越多天完成),更新答案即可。
最後再對每個點對 \(x,y\),我們把貢獻到 \((x,y)\) 上面的若干條路徑按照 \(tim\) 排序,然後預處理字尾 min,即可在 \(O(\log n)\) 的時間內回答一組詢問。這裡可能要對 \(O(n^2)\) 個長度為 \(O(m)\) 的陣列排序,但注意到對於一個 \(x\),所有 \(y\) 的分段點總共只有 \(O(m)\) 個,於是只需要進行 \(n\) 次排序。
綜上,總複雜度 \(O((n^2+m)m+nm\log m+q\log n)\)。
QOJ2573
給定 \(n,P\),對每個 \(s=0,1,\cdots,n^2\) 求出:
- 有多少個長為 \(n\) 的排列 \(p\) 滿足 \(\sum_{i=1}^n\max(p_i,i)=s\)。
答案對 \(P\) 取模。\(1\le n\le 150,10^8\le P\le 10^9+7,P\) 是質數。
考慮轉化為有多少對長為 \(n\) 的排列 \((p,q)\),滿足 \(\sum_{i=1}^n\max(p_i,q_i)=k\),然後把答案除掉 \(n!\)。
從大到小填數,設 \(f(i,j,s)\) 表示填了 \(i,i+1,\cdots,n\),目前有 \(j\) 個位置重疊,總和為 \(s\) 的方案數。
考慮如何轉移 \(f(i+1,j,s)\to f(i,j,\cdot)\)。
算出未重疊的部分個數為 \(k=n-i-j\),新填入兩個 \(i\),那麼有如下方案:
- \(p\) 那邊填到和 \(q\) 重疊的位置,\(q\) 那邊也和 \(p\) 重疊:\(f(i+1,j,s)\times k^2\to f(i,j+2,s)\)
- \(p\) 填到和 \(q\) 重疊的位置,\(q\) 和 \(p\) 不重疊:\(f(i+1,j,s)\times k\times (n-j-2k)\to f(i,j+1,s+i)\)
- \(p\) 不重疊,\(q\) 重疊:\(f(i+1,j,s)\times k\times (n-j-2k)\to f(i,j+1,s+i)\)
- 兩邊都不重疊,但新填入的兩個 \(i\) 位置相同:\(f(i+1,j,s)\times (n-j-2k)\to f(i,j+1,s+i)\)
- 兩邊都不重疊且兩個 \(i\) 位置不相同:\(f(i+1,j,s)\times 2\times \binom{n-j-2k}{2}\to f(i,j,s+2i)\)
綜上本題在 \(O(n^4)\) 時間內解決。
胖朵說:從小到大插入每個數,維護當前的置換環形態,考慮置換環每條邊的貢獻,記錄 \(f_{i,j,s}\) 表示當前插入到 \(i\),有 \(j\) 個置換環現在還長成鏈的樣子,目前所有邊的貢獻之和為 \(s\)。轉移有:
- \(i\) 獨自新開一個點,然後還需要再分要不要和自己連成自環兩種情況。
- \(i\) 連線兩條鏈。
- \(i\) 把一條鏈變成了一個環。
這樣不用除掉 \(n!\),嗯
QOJ2568 加好多 0
對於一個 \(n\times m\) 的矩陣 \(a\),其中每個 \(a_{i,j}\) 都是非負整數,你需要找到一條 \((1,1)\) 到 \((n,m)\) 的路徑,滿足每一步只能向右或向下走(即 \((i,j)\to (i,j+1),(i,j)\to (i+1,j)\)),你希望最大化這條路徑所經過的格子上的 \(a\) 之和。定義上述問題的答案為 \(f(a)\)。
有 \(q\) 次詢問,每次給出 \(n,m,k\),問有多少個 \(n\times m\) 的矩陣 \(a\) 滿足 \(f(a)=k\)。
答案對 \(998244353\) 取模。
\(1\le n,m,k\le 5\times 10^6,1\le q\le 10^6\)。
首先我們把 \(f(a)=k\) 放寬成 \(f(a)\le k\)。
考慮一個 \(f(a)\) 怎麼算,設 \(dp_{i,j}\) 表示走到 \((i,j)\) 的最小代價,有
我們發現,實際上 \(a\) 矩陣和 \(dp\) 矩陣是一一對應的關係,如果確定了 \(dp\),那麼有
於是我們考慮對合法的 \(dp\) 矩陣計數。
那麼只需要 \(dp_{n,m}\in[0,k]\),而且需要滿足 \(dp_{i,j}\ge \max(dp_{i-1,j},dp_{i,j-1})\)。
這是一個經典問題,我們考慮對每個 \(0\le i<k\) 畫出 \(\le i\) 的部分和 \(>i\) 的部分的分界線,那麼它們幾乎構成了 \(k\) 條 \((0,m)\) 到 \((n,0)\) 的路徑組,但它們可能會相交。我們考慮把第 \(i\) 條線向右下移動 \(i-1\) 格,那麼就可以得到 \(k\) 條 \((x,m+x)\) 到 \((n+y,y)\) 的不相交路徑組。使用 LGV 引理求解,時間複雜度為 \(O(n+m+k^3)\)。
實際上,可以證明該矩陣的行列式為(或者運用楊表相關結論,也可以得到):
注意到 \(i+j+l\le n+m+k\),我們對每個 \(p\le n+m+k\) 計算其係數 \(c_p\),則答案為 \(\prod_{p=3}^{n+m+k}\left(\frac{p-1}{p-2}\right)^{c_p}\),其中 \(c_p\) 是 \(1\le i\le n,1\le j\le m,1\le l\le k\) 且 \(i+j+l=p\) 的 \((i,j,l)\) 個數。\(c_p\) 可以使用容斥原理計算,拆開後發現只需要算若干 \(\prod_{i=1}^x i!\) 以及它們的逆元這樣的形式。
於是可以在 \(O(n+m+k+q)\) 的時間內解決這個問題。
Luogu8114
和上題一模一樣哈哈
LOJ3695
對於一個區間 \([l,r]\),如果 \(\sum_{i=l}^ra_i<\min(a_{l-1},a_{r+1})\),稱這樣的區間 \([l,r]\) 為阻塞區間。
這裡認為 \(a_0=a_{n+1}=\infty\)。
首先有一些顯然的性質:阻塞區間的個數不超過 \(2n\),且兩個阻塞區間要麼包含,要麼不交。考慮一次詢問 \([L,R]\),發現如果 \(i\) 不合法了,意味著有一個阻塞區間 \(i\in[l,r]\subseteq [L,R]\) 使得它不合法了。同理也可以發現,如果不存在包含 \(i\) 的阻塞區間,那麼 \(i\) 一定合法。
考慮直接用線段樹維護當前節點 \([L,R]\) 內還有多少個點沒有被阻塞區間覆蓋。合併的時候,有可能左邊的一段字尾和右邊的一段字首本來都是阻塞區間,但它們合併起來之後就合法了。注意到這些區間的個數不超過 \(O(\log V)\),而且這些區間之間都是互相相交的,我們只需要找到最大的一個阻塞區間。雙指標即可。
綜上,時間複雜度 \(O(N\log V+Q\log N\log V)\),其中 \(V=10^9\) 為值域。
我比較懶,程式碼寫的多了一個 \(\log V\),看上去跑的也非常快啊,最慢的點才 0.8s 左右。
QOJ4805
給定一個 \(n\) 點 \(m\) 邊的無向圖,第 \(i\) 個點上有一個標號 \(p_i\),其中保證 \(p_1,p_2,\cdots,p_n\) 是一個 \(1\) 到 \(n\) 的排列。
再給定兩個點 \(A,B\)(\(1\le A,B\le n,A\neq B\)),認為一個標號方案 \(p\) 是好的,當且僅當:
- 對每個節點 \(x\),都存在一條從 \(A\) 開始,到 \(B\) 結束的路徑,滿足這條路徑經過 \(x\),且路徑上的點的標號嚴格遞增。
一開始這張圖不一定是好的,你可以進行至多 \(999\) 次操作,每次操作可以選擇一條從 \(A\) 開始的簡單路徑,然後把它們的標號迴圈左移一位。具體來說,如果你選擇的路徑是 \(x_0(=A),x_1,\cdots,x_{k-1}\),設 \(y_i=p_{x_i}\)(\(0\le i\le k-1\)),操作完之後,所有 \(p_{x_i}\) 會同時變成 \(y_{(i+1)\bmod\ k}\)。
\(2\le n\le 1000,1\le m\le 2000,1\le A,B\le n,A\neq B\)。
首先有解需要縮點之後圓方樹形成一條鏈,且 \(A,B\) 分別在兩端。
於是我們考慮先構造一個這張圖 \(A\to B\) 的雙極定向,然後在雙極定向得到的 DAG 上按照拓撲序逆序考慮每個點,動態維護點集 \(S\),保證 \(S\) 中的每個點到 \(B\) 的路徑上點權均遞增。初始 \(S=\{B\}\),考慮依次加入每個點 \(u\),那麼進行 \(n\) 次之後,點集就會變成 \(\{1,2,\cdots,n\}\)。
現在的問題是,有可能加入的這個點 \(u\) 的點權會比它的後繼要大。我們任取一條 \(A\to u\) 的路徑,易知此時 \(A\to u\) 路徑上的所有點目前都不在 \(S\) 內。找到 \(u\) 的後繼中點權最小的一個點 \(v\),討論一下:
- 如果 \(p_v>p_A\),那麼我們直接對 \(A\) 到 \(u\) 這條路徑 shift 一下,那麼新的 \(p_u\) 變成了 \(p_A\),而且這個值比他的後繼節點的點權都要小。
- 如果 \(p_v<p_A\),我們把 \(v\) 也加入到操作路徑的末尾,然後接著從 \(v\) 開始找,直到滿足上面的條件,或者 \(u=B\)。此時,考慮我們第一次找到某個 \(x\) 滿足 \(x\) 的所有後繼節點權值都 \(>p_A\) 的這個時候,會把路徑 \(A\to x\) 整體左移,那麼新的 \(p_u\) 就變成了 \(p_v\),由於 \(p_v\) 是原先 \(u\) 的後繼中點權最小的節點,於是它小於 \(u\) 的其他後繼節點的點權;另一方面新的 \(p_v\) 變成了 \(v\) 的某個後繼 \(w\) 的 \(p_w\),由於原先 \(v,w\in S\),所以必有 \(p_v<p_w\)。類似地,此時每個節點都會滿足條件。
綜上我們成功用一次操作完成了擴充套件,於是只需要 \(n-1\) 次操作就可以把 \(S\) 擴充套件到整個集合 \(\{1,2,\cdots,n\}\)。
演算法的時間複雜度為 \(O(n^2)\),操作次數為 \(n-1\)。
幽蝶能留一縷芳
只關注 \(1\to 2\) 什麼時候可行,然後把答案乘上 \(N(N-1)\)。
- \(1,2\) 都在環外
那麼 \(dis=k\) 的方案數是
這個怎麼最佳化?草了,改一下列舉物件,得到
這個倒是好最佳化。
對於一個 \(L\),不難算出最小的合法的 \(R\) 是
於是合法的 \(L,R\) 數量是 \(f_k=\sum_{L=1}^kn-(L+\lceil\frac{k\ \bmod \ L}{\lfloor k/L\rfloor}\rceil)+1\),這部分可以用整除分塊最佳化。
- \(2\) 在環內
發現只要能同時走 \(p,p+1\),由於 \(\gcd(p,p+1)=1\) 我們肯定能走回來。
於是 \(R\ge L+1\) 的 case,都一定合法;否則設環長為 \(m\),\(dis(1,2)=k\),那麼需要 \(\gcd(m,L)\mid k\)。
可以列舉約數計算。考慮怎麼算方案數。這個簡單很多啊是不是,也是和上面類似的東西。
這樣總複雜度就 \(O(n\sqrt{n})\)。唉這個題真的是,我寫了一上午
LOJ3685
沒看到要求是最短路徑,我說這不是 circus P 嗎
那要求最短路徑的話,猜一下,如果合法那麼存在一種方案使得,每個人都是開始走之後,立刻直接走完。
這個怎麼判呢,感覺一下,如果 \((i,j)\) 滿足 \(S_i\in\text{path}(S_j,T_j)\) 或者 \(T_j\in \text{path}(S_i,T_i)\),那麼 \(i\) 就得在 \(j\) 前面走。這樣會連出來一張有向圖,如果是 DAG 就有解,否則無解。
但是邊數還是 \(O(m^2)\) 怎麼辦呢,考慮隨便拉個資料結構最佳化建圖,就可以做到 \(O(m\log n)\)。
考慮尋找合法解的性質,發現如果有解,那麼一定存在一種方案使得每個人開始走之後,直接不停頓地走到終點。
證明:考慮合法解中某個人 \(i\) 的相鄰兩次行動 \(A\to B,B\to C\),由於走的是最短路徑,必有 \(A\neq B\neq C\)。
我們考慮如果這兩次行動在總的行動序列上不相鄰,它們中間有若干次行動,由於此時 \(i\) 位於點 \(B\),因此其他人的任意行動都不能經過 \(B\)。以 \(B\) 為根建樹,那麼中間的行動可以劃分為三部分:
- 完全在 \(A\) 子樹內的部分
- 完全在 \(C\) 子樹內的部分
- 其他的部分
借用官方題解的圖:
於是我們可以重排操作序列為:
- 先進行完全在 \(C\) 子樹內的部分。
- 然後讓 \(i\) 這個人從 \(A\to B\to C\)。
- 然後進行 \(A\) 子樹內的部分和其他部分。
這樣一直操作下去,一定可以構造出一種解滿足每個人開始走之後,直接不停頓地走到終點。
於是我們考慮兩個人 \((i,j)\) 如果滿足 \(S_i\in\text{path}(S_j,T_j)\) 或者 \(T_j\in \text{path}(S_i,T_i)\),那麼 \(i\) 就得在 \(j\) 前面走。這樣會連出來一張有向圖,如果是 DAG 就有解,否則無解。
直接連會得到 \(O(M^2)\) 條邊,許多資料結構都能將其邊數最佳化至 \(O(M\log N)\)。
LOJ3687
首先,當 \(i<j\) 時,\(T_i\le T_j\) 等價於 \(s[i+1,j]\le s[i,j-1]\)。
也就是說,區間 \([i,j-1]\) 內第一個滿足 \(s_k\neq s_{k+1}\) 的位置 \(k\) 需要滿足 \(s_k\ge s_{k+1}\)。
另一方面,如果 \(i>j\),那麼相當於區間 \([j,i-1]\) 內第一個滿足 \(s_k\neq s_{k+1}\) 的位置 \(k\) 滿足 \(s_k\le s_{k+1}\)。
稱 \(i<j\) 的限制 \(T_i\le T_j\) 為第一類約束區間 \([i,j-1]\),否則為第二類約束區間 \([j,i-1]\)。
直接記錄 \(f(i,j)\) 表示前 \(i\) 個字元,\(s_i=j\) 的方案數。轉移時,我們分三種情況討論:
- \(s_i=s_{i+1}\):此時沒有約束,直接轉移 \(f(i,j)\to f(i+1,j)\)。
- \(s_i>s_{i+1}\):列舉上一個 \(s_k\neq s_{k+1}\) 的位置 \(k\),那麼要求 \(i\) 能滿足所有 \(l>k,r\ge i\) 的 \([l,r]\) 的約束,也就是不能存在第二類約束區間,滿足 \(k<l\le i,r\ge i\)。合法的 \(k\) 是一段字尾,可以拿 set 簡單維護得到這段字尾。得到合法字尾之後有 \(f(k+1,j)-f(k,j)\to f(i+1,[x<j])\),可以簡單做到 \(O(1)\) 轉移。
- \(s_i<s_{i+1}\):類似。
綜上,總複雜度 \(O(n|\Sigma|+n\log n)\),其中 \(|\Sigma|=26\)。
LOJ3688
顯然任意時刻 \(X,Y\) 肯定是最終串的一個區間,因此我們考慮區間 DP。
設 \(f(l,r)\) 表示合成 \([l,r]\) 所需的最小代價,分最後一次有效操作是貼上還是加字元討論。
如果是加字元,有 \(f(l,r)\leftarrow f(l,r-1)+A\)。
如果是貼上,那麼如果貼上了一個 \([k+1,r]\),考慮到剪下的時候會直接變成空串,於是我們一定是先用最小代價構造出 \(s[k+1,r]\),然後需要算出,如果剪貼簿裡面是 \(s[k+1,r]\),那麼構造出 \(s[l,r]\) 最少需要多少代價。
如果貼上一次還不如直接加字元,即 \(A\times (r-k)<C\),那顯然沒有用。
否則我們應該貼上儘可能多次,也就是說要在 \([l,r]\) 中找到儘可能多的不交子串 \(s[k+1,r]\)。
考慮先列舉 \(r\),然後列舉 \(k\),對所有的 \(l\) 做貢獻。列舉完 \(r,k\) 之後,設 \(c_i\)(\(i\le r\))為 \([i,r]\) 中子串 \([k+1,r]\) 的最多不交出現次數,我們相當於要做轉移
注意到 \(c_i\le \frac{r}{r-k}\),考慮對一段相同的 \(c_l\) 一起做貢獻,那麼是一個區間對公差為 \(A\) 的等差數列 chkmin 的形式,可以簡單維護。這樣對一個 \(r\),只需要 \(O(r\log r)\) 次區間 chkmin。進一步發現區間可以放寬成字首,於是可以 \(O(1)\) 進行一次操作。
現在還需要求一個 \(p\) 前面 \([l,r]\) 最後一次出現的位置,注意我們會對一個 \([l,r]\) 詢問若干遞減的 \(p\),在 SAM 上定位到 \([l,r]\) 這個節點,然後在 endpos 集合裡維護一個指標即可做到均攤 \(O(1)\)。
綜上,總複雜度 \(O(N^2\log N)\)。
LOJ3690
這什麼垃圾啊?
按 \(X\) 排序,欽定 \(X\) 最大的為 \(i\),那麼需要選出 \(j,k\) 滿足 \(j,k<i\),且 \(Y_j>\max(Y_k,Y_i),Z_k>\max(Z_j,Z_i)\)。
動態維護當前集合 \(S\),每次加入一個 \((Y_i,Z_i)\),先欽定他的 \(Y\) 最大,那麼剩下那個人的 \(Z\) 儘可能大肯定最優,只需要查詢 \(Y_j<Y_i\) 的 \(Z_j\) 的最大值。把這個 \((Y_i,Z_j)\) 加入答案集合 \(T\),類似地也對 \(Z\) 做一遍,每次查詢時,只需要查詢右上角的 max。是三維偏序的形式,使用任意資料結構即可簡單做到 \(O(N\log^2N)\)。
我是弱智。這我得坐起來跟他打。
考慮直接取出 \(X,Y,Z\) 最大的三個,發現如果有一個 \(i\) 滿足他的兩維都是 max,那麼這個 \(i\) 不可能在答案中,我們刪掉這個 \(i\),然後接著做下去;否則這個就是答案。時間複雜度 \(O(N\log N)\)。
LOJ3692
這什麼垃圾啊?等會兒,感覺這個 \(O((N+Q)D)\) 還算有意思,還是坐起來跟他打吧
大概想了一些別的做法,比如說點分樹可以 \(O((N+Q)\log^2N)\);考慮用一下 \(D\le 40\),每個點開一個長為 \(D\) 的分治結構。為了去除同子樹貢獻,有一些解決方案:對每個點的兒子再開一個分治結構,或者是單獨把貢獻減掉。由於 \(L\) 不一定是質數,沒辦法求逆元;但是注意只有乘除法,我們可以對 \(L\) 的每個質因子單獨維護指數,這樣做一次運算會多帶上 \(\omega(L)\) 的複雜度。
於是有 \(O(N+QD\log D\log N)\) 或者 \(O(N+QD\omega(L)\log D)\) 等等做法。
對於修改,如果修改了和 \(u\) 距離不超過 \(D\) 的一個點 \(v\),我們發現在 \(\text{LCA}(u,v)\) 處計算貢獻似乎不可避免地要帶上 log。設 \(\text{dist}(u,v)=x\le D\),我們考慮在 \(\text{LCA}\) 的 \(\lfloor\frac{D-x}{2}\rfloor\) 級祖先 \(p\) 的位置計算貢獻。
那麼要求 \(\text{dist}(u,p)+\text{dist}(p,v)=D\) 或者 \(D-1\)。可以發現,這樣的確能不重不漏地統計完所有貢獻。具體來說,對每個點 \(u\) 我們記錄 \(f_{u,i}\) 表示 \(u\) 子樹內和他距離為 \(i\) 的所有點進行的修改。修改時我們列舉 \(u\) 的祖先 \(p\),將 \(f_{p,D-\text{dist}(u,p)}\) 和 \(f_{p,D-1-\text{dist}(u,p)}\) 計入這次貢獻。查詢時列舉 \(v\) 的祖先 \(p\),把 \(f_{p,\text{dist}(u,p)}\) 累計進答案。
有一個細節是 \(\text{LCA}\) 可能不存在 \(\lfloor\frac{D-x}{2}\rfloor\) 級祖先,我們在根節點往上再加 \(D\) 個點即可。
總複雜度 \(O((N+Q)D)\)。常數非常小,目測應該比我上面扯的那些做法要快很多。
CF1400F
考慮直接 DP 最後保留的數構成的子序列,有一個暴力 DP 是,\(f_{i,S}\) 表示前 \(i\) 個數,目前序列最長的一個和 \(\le x\) 的字尾裡面的數為序列 \(S\),最多能留幾個數。但是 \(S\) 的狀態數可以有 \(2^x\) 種。
草了,衝一下這個做法,欸,怎麼 TLE 了啊?
思考。看上去他真的把我 \(2^x\) 幾乎卡滿了,這麼有實力?
那說明合法的狀態其實比不合法的狀態要多特別多,我可以只考慮把所有不合法的狀態拎出來然後相當於不能匹配上他們中的任何一個。建一下 ACAM 直接做就好了。
QOJ7185
給定一個二分圖,左邊有 \(n\) 個點,右邊有 \(m\) 個點,右邊每個點有容量,左邊第 \(i\) 個點和右邊第 \(j\) 個點之間的邊權為 \(c_{i,j}\)。對每個 \(k=1,2,\cdots,n\),求流量為 \(k\) 的最小費用流。
\(1\le n\le 50000,1\le m\le 10,1\le c_{i,j}\le 10^9\)。
首先建出費用流圖,把 \(s,t\) 和右邊的 \(m\) 個點稱作關鍵點。
考慮維護每兩個關鍵點之間不經過其他關鍵點的可能路徑集合,這樣每次我們在增廣時如果要求出 \(s\to t\) 的最短路,只需要在關鍵點之間跑最短路。
考慮得到一個增廣路之後如何模擬增廣,注意到我們不需要考慮和 \(s,t\) 相關的反向邊,因此關鍵點之間不經過其他關鍵點的最短路形態實際上相當簡單,本質上只有以下幾種:
- \(s\) 到某個右部點 \(R_j\):經過某個還未匹配的 \(L_i\),路徑形如 \(s\to L_i\to R_j\)。
- 右部點之間:\(R_j\to L_i\to R_k\)。這裡一定只會經過一個左部點,因為不能經過別的右部點。
- 右部點到 \(t\):直接走 \(R_j\to t\)。
我們可以在每個左部點 \(L_i\) 處把經過 \(L_i\) 的路徑的貢獻算進去。
由於我們找到的最短路的長度也是 \(O(m)\) 級別,對這條最短路經過的左部點重新計算它們的貢獻即可。
求最短路每次需要 \(O(m^2\log n)\) 建邊,然後 \(O(m^3)\) 求解最短路;重新計算左部點貢獻時,每個左部點最多隻有兩條鄰邊會翻轉,只會影響 \(O(m)\) 種決策。一共只有 \(O(m)\) 個左部點,故這部分複雜度也是 \(O(m^2\log n)\)。
綜上,本題在 \(O(n(m^2\log n+m^3))\) 時間內解決。
AGC018C Coins
反悔貪心可以匯出一個做法。考慮建圖跑費用流:
左邊建 \(n\) 個點 \(P_1,P_2,\cdots,P_N\),連邊 \(s\to P_i\),邊權 \(0\) 容量 \(1\)。
右邊建三個點 \(A,B,C\),都連到 \(t\),邊權 \(0\) 容量分別為 \(X,Y,Z\)。
每個 \(P_i\) 連三條邊 \(P_i\to A,B,C\),邊權分別為 \(a_i,b_i,c_i\),容量為 \(1\)。
於是就變成了 QOJ7185,套過來就行。這裡 \(n\le 10^5,m\le 3\)。
https://atcoder.jp/contests/agc018/submissions/52902728
[NOI2019] 序列
每個點有四種決策:兩邊都不選,\(a\) 那邊選,\(b\) 那邊選,\(a,b\) 同時選。
對後三種決策建出三個點 \(Q_{1\cdots 3}\),但是我們發現沒辦法直接確定某個 \(Q_i\to t\) 的流量。
具體來說我們實際的約束是:
- \(Q_3\to t\) 的流量 \(\ge L\);
- \(Q_1\to t,Q_3\to t\) 的流量之和為 \(K\);
- \(Q_2\to t,Q_3\to t\) 的流量之和為 \(K\)。
樸素的想法是列舉 \(Q_3\to t\) 的流量 \(d\ge L\),可以得到 \(Q_1,Q_2\to t\) 的流量均為 \(K-d\),然後跑 QOJ7185。
但是每次跑一遍複雜度至少為平方,考慮 \(d\) 每增加 \(1\),相當於我們要進行兩次退流 \(t\to Q_1\to s,t\to Q_2\to s\),再進行一次增廣 \(s\to Q_3\to t\)。對於增廣我們正常做,對於退流改成求 \(t\to s\) 的最長路即可。
此時由於我們反過來要求 \(t\to s\) 的最長路,還需要額外維護 \(Q_i\to s\) 的最長路。
總複雜度仍然是 \(O(n\log n)\)。 這個做法的常數有點大...不太能過的樣子QAQ
AGC034D Manhattan Max Matching
設 \(M\) 為紅球總數。考慮把 \(|x_i-x_j|+|y_i-y_j|\) 拆成
那麼會得到四種符號,我們在中間建四個點分別表示 \((+,+),(+,-),(-,+),(-,-)\) 四種符號。
接下來對每個紅球 \(i\) 我們都連向中間四個點,邊權分別為 \(x_i+y_i,x_i-y_i,-x_i+y_i,-x_i-y_i\);然後另一邊的每個藍球 \(i\) 我們也從中間四個點連到他,邊權分別為 \(-x_i-y_i,-x_i+y_i,x_i-y_i,x_i+y_i\)。
那麼這個問題就變成和 QOJ7185 幾乎一樣的形式了,只不過此時是中間有四個點,左右兩側各有 \(M\) 個點。類似地維護中間四個點 \(Q_1,Q_2,Q_3,Q_4\) 它們 \(Q_i\to Q_j\) 的最短路,然後再維護 \(s\to Q_i,Q_i\to t\) 的最短路即可。
時間複雜度:\(O(M\log M)\) 帶很大常數。
[SD2024 一輪省集] Circuits - By alpha1022
二維平面上有 \(n+m\) 個點 \((x_1,y_1),(x_2,y_2),\cdots,(x_n,y_n)\) 和 \((a_1,b_1),(a_2,b_2),\cdots,(a_m,b_m)\)。
現在所有的 \((x_i,y_i)\)(\(1\le i\le n\))已經按照 \(1,2,\cdots,n\) 的順序連成一個環。現在你可以選擇 \(k\) 個 \((a_j,b_j)\) 和環上的 \(k\) 條邊,把你選的 \((a_j,b_j)\) 按照任意順序分別插入到這 \(k\) 條邊的中間。這裡每條邊裡面至多插入一個 \((a_j,b_j)\),每個 \((a_j,b_j)\) 最多被選中一次。
在做完上述操作後會得到一個 \(n+k\) 個點的環,定義該方案的分數為所有邊的兩端點的曼哈頓距離之和。此外,如果選中了 \((a_j,b_j)\),分數還會額外加上 \(w_j\)。你希望最大化這個方案的分數。
你需要對 \(k=1,2,\cdots,n\) 求出上述問題的答案。
\(1\le n\le m\le 10^5,-10^8\le a_i,b_i,x_i,y_i,w_i\le 10^8\)。
考慮一個點 \((a_i,b_i)\) 和一條邊匹配,權值為
這裡根據 \(a_i\) 和這兩個 \(x\) 的大小關係,以及 \(b_i\) 和這兩個 \(y\) 的大小關係,可以拆出來 \(3\times 3=9\) 個點。
接下來類似上題進行建圖即可。複雜度 \(O((n+m)\log (n+m))\) 帶很大常數。
[2022 ICPC 杭州區域賽] H. RPG Pro League
你在玩一個遊戲,這個遊戲中有三類角色:輸出位,增益位,生存位。
一個隊伍由四個角色構成,每個隊伍必須形如:
- 兩個輸出位,一個增益位,一個生存位。
- 一個輸出位,兩個增益位,一個生存位。
現在有 \(n\) 個角色,第 \(i\) 個角色有一個可以擔任的位置集合 \(S_i\subseteq\{輸出,生存,增益\}\),讓這個角色加入隊伍的代價為 \(a_i\)。你希望組出最多的隊伍數量,在此基礎上求出最小的組隊代價。一個角色只能加入至多一個隊伍,且一個角色同時只能作為一個隊伍中的一個位置。
有 \(q\) 次修改,每次給出 \(x,v\),表示將 \(a_x\leftarrow v\)。每次修改後你都需要求出上述問題的答案。
\(1\le n,q\le 10^5,1\le a_i\le 10^9\)。
解法一(官方做法)
考慮先算出最多能組多少隊,然後再算出最小代價。把三種角色稱為 A,B,C
類角色。
建一張圖,左邊有 \(4\) 個點分別代表 \(\{A\},\{B\},\{C\},\{A,B\}\),右側七個點分別代表 \(A,B,C\) 的任意非空子集。右側點 \(T\) 的點權就是所有 \(i\) 裡面 \(S_i=T\) 的 \(i\) 的個數,對於左側點 \(U\) 和右側點 \(V\),如果 \(U\cap V\neq\varnothing\) 就連邊。
現在相當於求這個二分圖的多重最大匹配。
我們知道由 Hall 定理,存在 \(k\) 重完美匹配當且僅當 \(\forall S,|N(S)|\ge k|S|\)。於是答案就是
考慮如何算最小代價,按照權值從大到小依次考慮每個數,如果能刪除他就刪除。這裡容易用貪心解釋,也可以用擬陣來解釋。那麼修改的時候可能會刪除一個數,插入一個數。類似人員排程那題進行維護即可。
解法二
還是考慮建那個圖,只不過我們一開始就直接區分所有點。那麼建出來的費用流圖有三種邊:
- \(s\to P_i\)(\(1\le i\le n\)),容量 \(1\) 邊權 \(a_i\)。
- \(P_i\to Q_j\)(\(1\le j\le 4\)),容量 \(1\) 邊權 \(0\)。
- \(Q_j\to t\)(\(1\le j\le 4\)),容量 \(ans\) 邊權 \(0\)。
其中 \(ans\) 是我們求出來的答案。為了求這個答案,可以考慮每次依次把 \(Q_j\to t\) 的邊一條一條增廣,看能否增廣成功。如果成功了,就把 \(ans\leftarrow ans+1\)。我們一直增廣最短路就可以保證費用也是最小的。
現在還要修改 \(a_i\),怎麼辦?我們考慮此時如果 \(i\) 在匹配裡,那麼可能會增大 \(a_i\) 然後把他換成別的;如果 \(a\) 不在匹配裡,那麼可能會減小 \(a_i\) 然後把匹配裡的一個點換成他。
如果把 \(i\) 換成了 \(j\),畫一下增廣路,發現形如 \(s\to i\to Q_x\to j\to s\)。也就是說我們只需要判斷是否存在一個負環。這怎麼看都是隨便維護。