題解-2019省選題題解集合

這是一篇面向本身的文章…正在補坑…部分題目太水就不放代碼了html

省份 D1T1 D1T2 D1T3 D2T1 D2T2 D2T3
\(\mathrm {BJOI}\) X X X X
\(\mathrm {GZOI}\) X X X X
\(\mathrm {HNOI}\) X X
\(\mathrm {JSOI}\) N/A N/A N/A X
\(\mathrm {SDOI}\) X
\(\mathrm {SNOI}\) X X X
\(\mathrm {TJOI}\) X X X X
\(\mathrm {ZJOI}\) X X
\(12\)省聯考 X X X

BJOI2019

D1T1 奧術神杖

明顯能夠二分答案 \(a\)\(a\leq \sqrt[c]{\prod w_i}\Leftrightarrow a^c\leq \prod w_i\),設 \(w'=\frac wa\),則能夠在咒語構建出的 AC自動機 上 dp 了數組

D2T1 排兵佈陣

顯然對於每一座城堡,只有等於某我的+1時纔有可能成爲最優策略,作個揹包 \(O(nms)\)網絡

D2T2 光線

文章連接大數據

D2T3 刪數

\(b_i\) 爲值爲 \(i\) 的數的個數,發現 \(\forall i\in[1,n]\),若不存在 \(j\) 使得 \(i\in(j-b_j,j]\),則位置 \(i\) 須要一次「修改」,則答案就是統計位置 \([1,n]\) 共有多少位置須要「修改」優化

線段樹維護,可使用掃描線線段樹的技巧(加tag和刪tag一一對應,不用下推標記)。單點修改至關於區間修改幾回;總體加減一至關於將區間左右移,這個能夠記錄平移偏量,對進出右邊界的格子進行修改ui

Code編碼

GZOI2019

D1T1 與或和

位運算的題明顯按位拆開考慮,對於每一位至關因而問有多少個全 \(0/1\) 矩陣:枚舉矩陣的右下角,考慮左上角關於橫座標是一個單調棧,在掃描每一行的時候維護這個單調棧便可 \(O(n^2)\)spa

總複雜度 \(O(31n^2)\)code

D1T3 特技飛行

文章連接htm

D2T2 旅行者

二進制分組:進行 \(\log n\) 次分組,第 \(i\) 次按照關鍵點編號的二進制編碼下第 \(i-1\) 位是否爲一分類,每次求出從一個集合到另外一個集合的最短路。總複雜度 \(O((n+m)\log^2n)\),已然能夠經過此題

直接暴力:先跑一遍最短路,將邊反向後再跑一次最短路,考慮每條邊的貢獻(兩端點最近關鍵點的距離,如果同一個點則不予統計)。總複雜度 \(O((n+m)\log n)\)

D2T3 舊詞

作過 LNOI2014 lca 的能夠秒切,那題大概就是這題去掉上頭那個 \(k\) 次冪,下面是那題的題解:

能夠將一個點的深度轉換成該點到根節點的路徑上的點個數,那麼考慮將這個點的深度 \(dep\) 貢獻平攤到這個點到根路徑上的總共 \(dep\) 個點上去,每一個點貢獻爲一,那麼查詢這個點的權值就是查到該點到根的權值和

那麼 \(\sum_{i=l}^rdep[lca(i,z)]\) 的詢問就是:
\(l\)\(r\)這些點到根的路徑上的點的點權所有加一(每一個點都要加一次),最後詢問\(z\)到根路徑上的權值和,離線掃描便可。複雜度 \(O((n+m)\log^2n)\)

回到 GZOI 這題來,這題就只要在每一個點上預先設好 \(dep^k\) 的權值,加 \(1\) 變爲加對應的點的權值,線段樹也支持。複雜度不變依舊是 \(O((n+m)\log^2n)\)

HNOI2019

D1T3 多邊形

明顯這個多邊形的終態是點 \(n\) 連出 \(n-3\) 條邊,爲了達到最優解,則每次必定會連一條邊到 \(n\),同時也必定會存在這樣的一次操做,第一問得解

考慮第二問。模擬上頭的貪心,發現每次能夠將當前區段分爲兩段分治求解,即一棵樹結構,答案就是這棵樹不一樣的拓撲序數,拓撲序數的統計能夠在每一個節點處用組合數合併兒子們,作到這裏就有 \(65\) 分了

再考慮合併兒子的式子,能夠由 \(\prod \binom {sz_1+sz_2}{sz_1}\) 的形式轉成 \(\frac {sz_x!}{\prod_{x\rightarrow v}sz_v!}\),則計算了根節點後,其他節點的貢獻是 \(\prod \frac 1{sz_x}\) 的形式,而一條邊 \((x,y)\) 在樹上對應節點的子樹大小爲 \(|x-y|-1\)

至於怎麼快速進行一次旋轉,對於每一個點維護一個出邊集合,找前驅後繼便可

Code

D2T1 校園旅行

這題我在省選考場上被卡棧卡掉了 \(40pts\),並且出題人原本打算給個人作法 \(70pts\) 的,而後就成B類墊底了 (⊙v⊙)

可是這題的 \(70pts\) 作法和 \(100pts\) 作法是兩個方向 (∪_∪),myy的作法感受很妙

\(30pts\) 考慮一條迴文路徑在兩端加上一對相同的點也是迴文路徑,因此從一個點或者一條同色邊開始擴展,記憶化便可 \(O(n^2+m^2)\)

\(70pts\) 也差很少,只是在轉移時兩端不要同時轉移,先轉移一邊再轉移另外一邊,能夠作到 \(O(n^2+nm)\),可是實際在考場上測得只有 \(30pts\),數據只放過了 \(40pts\) 而後就被卡棧惹

正解依舊使用 \(30pts\) 作法,只不過將邊的數量縮小到 \(O(n)\) 級別:

  • 將邊分爲三類:兩端都是 \(0\);兩端都是 \(1\);一端是 \(0\) 一端是 \(1\)
  • 將三類邊每一類單獨建圖,對於每個聯通塊而言,若爲二分圖則保留一棵生成樹,不然在某一個點上加上一條自環

正確性很差說明,本身去理解比較好:對於任意一條原圖上的迴文路徑,可能會由於上面作法中只保留一棵生成樹而毀壞,但連通性仍是能夠保證的,並且能通過保留的生成樹找到對應同奇偶的替代方案(若這個圖不是二分圖就要加自環 是由於原圖中能夠改變這個點的奇偶性,而新圖中能夠依據這條自環改變奇偶性)

Code

JSOI2019

D2T2 神經網絡

反正這些細節我是想不出來

先不考慮迴路的事。

首先明確這個圖中的哈密頓路至關於將這個森林中每一棵樹都剖成若干段,將這些段排成一列,任意相鄰兩段不能排成一列

能夠發現這個東西能夠容斥,更具體的,能夠算出每棵樹的容斥係數,最後相乘:

\(s[i][j]\) 表示將 \(i\) 個元素排成 \(j\) 個排列的方案數,能夠先考慮劃分紅 \(j\) 個集合的方案數,最後再乘 \(j!\)

\(g[i]\) 表示將這棵樹劃分爲 \(i\) 條鏈的方案數,設 \(f[i][j][0/1/2]\) 來樹形Dp可得

則這棵樹剖出 \(i\) 段的容斥係數爲 \(F_i=\sum_{j=i}^n(-1)^{j-i}g[j] \cdot s[j][i]\),將這個乘到總的序列裏去(須要根據位置乘組合)

再回來考慮迴路的問題,只須要限定第一棵樹的 \(1\) 號點所在鏈爲起點,且最後一條鏈不能在第一棵樹上

至於 \(s\) 數組,考慮先用 \(s'[i][j]=\sum_{k=j-1}^{i-1}s'[k][j-1]\) 轉移,再 \(s[i][j]=s'[i][j]\cdot j!\)(實際上能夠發現 \(s[i][j]=\binom {i-1}{j-1}\cdot j!\)

以及 \(f\) 數組:

\[ f'[x][i+j][0] += f[x][i][0] \cdot \sum f[v][j][0/1/2] \]

\[ f'[x][i+j-1][1] += f[x][i][0] \cdot f[v][j][0]\cdot 2\\ f'[x][i+j-1][1] += f[x][i][0] \cdot f[v][j][1]\\ f'[x][i+j][1] += f[x][i][1] \cdot \sum f[v][j][0/1/2] \]

\[ f'[x][i+j-1][2] += f[x][i][1] \cdot f[v][j][0]\\ f'[x][i+j-1][2] += f[x][i][1] \cdot f[v][j][1] \cdot \frac 12\\ f'[x][i+j][2] += f[x][i][2] \cdot \sum f[v][j][0/1/2] \]

Code

SDOI2019

D2T2 移動金幣

首先能夠將每枚金幣看作一堆石子,這堆石子的個數就是這枚金幣與其左端最近金幣的距離,每次能夠選擇一個第 \(i\) 堆的若干石子放入第 \(i+1\) 堆。

這是反過來就是一個「階梯nim」遊戲,一個結論是若奇數位的石子數異或和爲零則先手必敗,其餘狀況先手必勝

\(50pts\) 的子任務就能夠暴力Dp了。

對於滿分子任務,考慮設 \(f[i][j]\) 表示考慮由大到小的前 \(i\) 個二進制位異或和都爲零,且目前這些位上的和爲 \(j\) 的方案數。轉移考慮對於當前位,在奇數位上放了偶數個 \(1\),並考慮偶數位上的隨意防止,組合數轉移便可。詳見代碼

Code

SNOI2019

D1T1 字符串

看到有人用 \(O(n\log n)\) 的作法,其實能夠 \(O(n)\)

明顯能夠將相鄰的相同字符合並,先處理完相鄰字符都不同的狀況,最後在輸出時一塊兒輸出。好比 aaabb,能夠先將 aaabb 分別合併,獲得 ab,排序可得答案爲 4 1,再將剛被合併的相鄰相同字符放進去,獲得 (4) 5 (1) 2 3(其中打括號的爲合併後的答案,無括號的即剛加入字符)

那麼只需考慮相鄰字符不一樣的狀況惹。對於比較 \(s_i,s_j(i<j)\),只需考慮 \(a_i,a_{i+1}\) 的大小關係便可。如此能夠知道對於每個 \(s_i\),它與每個 \(s_j(i<j)\) 的大小關係都是同樣的,那麼能夠將 \(s_i\) 放在全部 \(s_j(i<j)\) 的前/後邊,只要從後往前維護,就能夠鏈表維護惹(須要維護在鏈表先後插值)。空間時間複雜度都爲 \(O(n)\)

Code

D1T2 數論

枚舉 \(A\) 集合中的每個值,其對應的 \(x\) 知足\(a+Pt\equiv x \pmod Q\),左部在同餘狀況下是 \((P,Q)\) 個環,統計環的個數與多餘部分便可

Code

D1T3 通訊

建出費用流模型:拆點 \(i,i'\)

  • \(\forall i,s\rightarrow i,i'\rightarrow t\)
  • \(\forall i < j,i\rightarrow j'\)

這樣有 \(80pts\)

兩種方法優化建邊:

  • 主席樹:絕對值分兩個方向用主席樹優化建邊;
  • CDQ:對於每一層建出雙向導通的數軸,cdq的一端連入,另外一端連出

最後須要zkw費用流

Code

TJOI2019

D1T1 甲苯先生的字符串

矩乘快速冪模板題

D1T2 甲苯先生的滾榜

splay模板題

D2T1 大中鋒的遊樂場

剛看題只看到了 \(n\leq 10^4\),想了兩分鐘,而後看到了 \(k\leq 10\),而後就變成了——拆點最短路模板題

點數 \(2nk\),邊數 \(mk\),複雜度 \(O(T(n+m)k\log nk)\),但因爲大數據不超過兩個,可過

D2T2 甲苯先生和大中鋒的字符串

sam or sa 模板題

ZJOI2019

D1T2 線段樹

設已修改了 \(c\) 次,考慮其問題本質是對於 \(c\) 次修改,每一次修改選與不選共 \(2^c\) 棵線段樹的答案和。變相考慮在 \(2^c\) 棵樹中有 tag 的指望,最後乘上 \(2^c\) 即爲答案

進一步的,統計答案是枚舉線段樹的每個節點,求其有tag的指望和,最後乘 \(2^c\),因此目標是維護每一個節點有 tag 的指望

在草稿紙上對線段樹的區間修改進行模擬,發現修改路徑上的 tag 所有會消失,在修改路徑的末端打上一個 tag,而若修改路徑上的一個點 \(x\) 有 tag,則 \(x\) 如下的路徑旁的節點都會所以打上 tag

對每一個節點維護一個值 \(f\),表示這個節點有tag的指望;而爲了維護對修改路徑旁節點的影響,能夠考慮維護一個 \(g\) 值,表示在線段樹上這個點到根這條路徑上至少有一個 tag 的指望

整理一下,獲得:

  • 對於修改路徑上的節點:\(f=\frac 12f,g=\frac 12g\)(一半的狀況中不變,一半的狀況中 tag 消失)
  • 對於修改路徑旁的節點:\(f=\frac {f+g}2\)(一半的狀況中不變,一半的狀況中依賴於路徑上是否有 tag)
  • 對於修改路徑的末端:\(f=\frac {f+1}2\)(一半的狀況中不變,一半的狀況中必定存在 tag)
  • 對於修改路徑末端的子樹:\(g=\frac {g+1}2\)(同理……)

線段樹維護便可(對於屢次 \(g=\frac {g+1}2\) 的標記,若標記有 \(k\) 個,則推式子可得 \(g=1-\frac {1-g}{2^k}\)

D2T2 語言

  • \(20pts\):暴力掃描每一條路徑,複雜度 \(O(mn^2)\)
  • \(+20pts\):考慮對於每一個點能聯繫的點集,必定是一個連通子樹,可使用創建虛樹的方法求解,須要使用 \(O(1)\)\(lca\),複雜度 \(O(nm+n^2)\)
  • \(+20pts\)(鏈):考慮每條路徑是一段區間,而這個區間內部能夠連通,轉化爲一個矩形,掃描線求面積並(在一個上三角中),複雜度 \(O(m\log n)\)
  • 另外一個暴力:相似於上頭鏈的解法,使用樹鏈剖分,每條路徑會被劃分爲 \(\log n\) 段區間,相應產生 \(\log^2n\) 個矩形,掃描線複雜度 \(O(m\log^3n)\),實測 loj 可過,zjoi現場老爺機跑不動

關於 \(100pts\) 解法,是在第二檔部分分上的優化:

爲了避免在每一個點上從新枚舉全部路徑,能夠採用將路徑在樹上差分,而後每一個點繼承兒子信息(路徑 \((x,y)\):在 \(x,y\) 處增長此路徑,在 \(fa(lca(x,y))\) 處減去兩次此路徑

關於繼承兒子信息要麼是啓發式合併,要麼是線段樹合併,兩者在此題中都是 \(O(n\log n)\)

考慮到如今要維護虛樹大小,回顧虛樹的構建過程,不難發現虛樹大小等於 全部點深度和 減去 將點按 \(dfs\) 序排序後相鄰兩點 \(lca\) 的深度和,

  • 這玩意用啓發式合併便可
  • 也能夠用線段樹能夠輕鬆維護(下標爲 \(dfs\) 序,維護當前節點的標記次數、虛樹大小、該區間最左最右的關鍵點,上傳節點信息時如有標記,虛樹大小等於 左右虛樹大小之和 減去 左區間右端與右區間左端lca的深度)

Code

\(12\)省聯考

D1T1 異或糉子

相似於NOI2010超級鋼琴,明顯是求最大的 \(k\) 個區間,先求個異或前綴和

考慮構建一棵 \(trie\) 樹,將每一個點做爲右端點時對應的最大左端點求出來,放進堆裏(共 \(O(n)\) 個元素)

考慮每次從堆裏取出一個元素,統計答案後找到這個點的編號(右端點),再將這個右端點對應的還沒取的最大左端點放進堆裏……共取 \(k\) 次,複雜度 \(O((n+k)\log n)\)

至於如何維護每一個右端點已經取得的左端點,記錄 \(n\) 棵動態開點線段樹便可(結構與 \(trie\) 相同,在每次尋找時能夠快速斷定子樹內是否有未取得的左端點)

D2T1 皮配

文章連接

D2T2 春節十二響

每一個集合只有最大值有用,用最大值表示這個集合

鏈的部分分強烈明示處理兩條鏈的合併,不難猜想正解就是在每一個節點處合併全部的兒子

合併兩個兒子的信息至關於將兩個數組合併成一個新的數組,也就是說給兩個數組的元素之間兩兩匹配,\(a,b\) 匹配出的結果爲 \(\max(a,b)\)

貪心地考慮,若是如今有一個有序序列 \(\{a_1,a_2,a_3\}(a_1\leq a_2\leq a_3)\),要放入一個元素 \(b(a_1<b\leq a_2)\),則這個元素放入 \(a_2\) 比較優(由於這樣不會改變集合最大值之和,並且能爲後面的合併留下 \(a_3\) 這個更有用的選項)

而且合併時要先考慮大元素的合併,以防有小元素搶佔大元素

用 set 維護,啓發式合併就可作到 \(O(n\log^2n)\)

或者更乾脆點,兩個數組合並就按照從大到小兩兩合併(\(A\) 數組的第 \(k\) 大與 \(B\) 數組的第 \(k\) 大合併),用個堆便可

再者,有時間能夠寫成長鏈剖分,複雜度 \(O(n\log n)\),我懶因此代碼裏就直接啓發式合併了

Code

相關文章
相關標籤/搜索