1. 程式人生 > 實用技巧 >Luogu P4062 Yazid 的新生舞會

Luogu P4062 Yazid 的新生舞會

題目大意

\(n\) 個非負整數 \(a_1,a_2,\dots,a_n\) ,求有多少個區間 \([l,r]\) ,滿足 \(a_l,a_{l+1},\dots,a_r\) 中的眾數數量大於 \(\dfrac{r-l+1}{2}\)
其中, \(1 \leq n \leq 5 \times 10^5\)\(0 \leq a_i \leq n - 1\)

題解

觀察部分分,當 \(type = 2\) 時,容易發現,滿足條件的子區間長度不超過 \(2 \times 15\)
於是我們可以從 \(1\)\(n\) 列舉 \(l\) ,在從 \(l\)\(l + 30 - 1\)

列舉 \(r\) ,列舉時不斷更新當前子區間的眾數,並判斷是否滿足條件。
時間複雜度為 \(O(30n)\)

繼續觀察部分分,當 \(type = 3\) 時( \(type = 1\) 的情況實際上是 \(type = 3\) 的情況的子集),不同 \(a_i\) 的數量很少,最多隻有 \(8\) 種。
思考若一個區間眾數為 \(m\) ,眾數的數量為 \(c(m)\) ,若這個區間滿足要求,則必須保證 \(c(m)\) 大於區間長度的一半,即 \(c(m) > (r - l + 1) - c(m)\)
移項,得 \(2c(m) > r - l + 1\)
我們設區間 \([1,i]\)
中出現 \(m\) 的數量為 \(s(i)\) ,代入上式,得 \(2\left(s(r) - s(l - 1)\right) > r - l + 1\)
移項,得 \(2s(r) - r > 2s(l - 1) - (l - 1)\)
顯然我們可以用樹狀陣列等資料結構維護 \(2s(i) - i\)
所以我們可以先從 \(0\)\(7\) 列舉,設當前列舉到的數為 \(num\),再從 \(1\)\(n\) 列舉 \(a_i\) ,算出當前的 \(2s(i) - i\)insert ,每次貢獻的答案為 \(2s(j) - j\) 的數量,其中 \(0 \leq j \leq j\)
\(2s(j) - j < 2s(i) - i\)
時間複雜度為 \(O(8n\log n)\)

然而上面的做法貌似不能過部分分,所以還要繼續優化。
觀察得 \(2s(i) - i = \begin{cases} 2s(i - 1) - (i - 1) + 1 & a_i = m \\ 2s(i - 1) - (i - 1) - 1 & a_i \not = m \end{cases}\)
所以我們可以不用樹狀陣列來維護。
我們設 \(sum = \sum\limits_{j = 1}^{i - 1} (2s(j) - j)\left[2s(j) - j \leq 2s(i) - i\right]\) ,設 \(t(a_i) = \sum\limits_{j = 1}^{i}\left[a_j = a_i\right]\)
顯然,每列舉一個 \(a_i\)\(t(2s(i) - i) \gets t(2s(i) - i) + 1\)
\(a_i = m\) 時, \(sum \gets sum + t(2s(i) - i)\)
\(a_i \not = m\) 時, \(sum \gets sum + t(2s(i - 1) - (i - 1)) + 1\)\(sum \gets sum + t(2s(i) - (i) + 1) + 1\)
顯然時間複雜度為 \(O(8n)\)

此時我們考慮 \(type = 0\) 的情況即正解。 \(type = 2\) 時滿足條件的子區間長度較短, \(type = 3\) 時滿足條件的子區間內眾數的種類較少。
設滿足條件的子區間的最大長度為 \(p\) ,則按照 \(type = 2\) 的做法來做時間複雜度為 \(O(pn)\)
設滿足條件的子區間的眾數最多數量為 \(q\) ,其實就是不同 \(a_i\) 的數量,則按照 \(type = 3\) 做法來做時,時間複雜度為 \(O(qn)\)
考慮正解,我們是否可以綜合兩種做法的優點?