NOI2024 山東一輪省隊集訓

KingPowers發表於2024-04-03

Day 1

A. fibonacci

題目描述

\(S_0=\tt a\)\(S_1=\tt b\),定義斐波那契串 \(S_i=S_{i-1}+S_{i-2}\),加號表示拼接。

給定一個字串 \(t\),僅由字母 \(\tt ab\) 構成,求 \(S_{\infty}\) 最短的一個子串滿足 \(t\) 是該子串的子序列,輸出該子串長度。

\(1\le|t|\le1.5\times10^5\)

題目分析

首先答案一定不超過 \(3n\),因為生成的串不存在超過 \(2\) 個的連續相同字元,其次這個串也不需要生成很長,\(10^6\) 量級足矣。

然後考慮一件很厲害的事情,將 \(S\) 按照拼接方式劈開,得到一個類似線段樹的結構:

預處理 \(f[i][j]\) 表示當前 \(t\) 已經匹配了 \(i\) 位,再拿去和 \(S_j\) 匹配之後能匹配到第幾位,處理方式和倍增類似。

然後我們就得到了一個 \(O(\log n)\) 判斷 \(t\) 是否是 \(S\) 某個子串的子序列的方法:類似線段樹那樣拆成 \(O(\log n)\) 段小的 \(S_i\),每段利用上面預處理的那個陣列向後匹配。

直接雙指標掃描所有極短的 \(t\) 可匹配的子區間即可,時間複雜度 \(O(n\log n)\)

程式碼

點選檢視程式碼

B. tap

題目描述

平面上有 \(n\) 條線段,第 \(i\) 條線段兩個端點分別為 \((l_i,h_i)\)\((r_i,h_i)\),且每個線段中點上方 \(0.5\) 個單位處有個水龍頭。

開啟某個線段的水龍頭後,水會沿著這條線段兩端流下去,流到地板或下一條線段,且流到下一條線段後會繼續流。

按隨機順序開啟水龍頭,每次在沒有水的線段中等機率選一個開啟,問期望開啟幾次使所有線段有水。

\(1\le n\le 5\times 10^5\)\(\{l_i,r_i\}\) 構成 \(1\)\(2n\) 的排列,\(h_i=i\)

題目分析

考慮 \(O(n^2)\) 做法,我們將每個線段與兩個端點向下延長第一個碰到的線段分別連邊,這樣會連出來一個 DAG。

轉化下期望,根據期望的線性性等於求每個點被選到的機率之和,而一個點如果被選那麼此時所有能到達該點的其他點一定都沒有被選,也就是設算上點 \(i\) 能到達 \(i\) 的點有 \(C_i\) 個,那麼答案就是 \(\sum\frac{1}{C_i}\),可以類比一道叫 Game on Tree 的題。

繼續最佳化需要一個觀察,上一下課件裡的圖:

我們稱連向點 \(i\) 左端點的點為 \(i\) 的左父親,連向點 \(i\) 右端點的點為 \(i\) 的右父親,為了方便我們在 \(n+1\) 的高度新增一條無限長的線段。

那麼圖中 \(w\) 這種線段就相當於,從 \(u\) 開始一直跳左父親和右父親,最後跳到的同一個點就是 \(w\) 了。

先考慮些瑣碎的東西:

  • 建圖的最佳化,從高到低掃描線線段樹做區間覆蓋。
  • 求左右父親,從低到高掃描線線段樹做區間覆蓋。

然後考慮如何計算陰影中的線段數量,對於每條上下的邊我們維護其左邊有多少線段,右鏈左邊的總數減去左鏈左邊的總數就能算出來了,這個東西顯然可以差分一下,然後掃描線樹狀陣列維護。

至於最後的統計答案,倍增維護左右父親和鏈上的左側線段數量和,直接跳即可。

時間複雜度 \(O(n\log n)\),注意空間常數。

程式碼

點選檢視程式碼

C. polygon

題目描述

\(n\) 個實數 \(x_{1},x_{2},\ldots,x_{n}\)\(x_i\)\((0,2^{a_i})\) 的實數中等機率隨機,問不存在一個 \(x_i\) 超過 \(\sum x_i\) 的一半的機率。

\(1\le n\le 5\times 10^4\)\(0\le a_i\le 50\)

題目分析

有一說一,這題真不難。

但是需要多重積分和 NTT,不想寫了,有空回來把前一半步驟寫了。

相關文章