Luogu P4062 Yazid 的新生舞會
阿新 • • 發佈:2020-08-07
題目大意
有 \(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\)
時間複雜度為 \(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]\)
移項,得 \(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\)時間複雜度為 \(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)\) 。
考慮正解,我們是否可以綜合兩種做法的優點?