NOI online 2021 島嶼探險

NOI online 2021 島嶼探險

場上寫了個被卡常的時間\(n\log^2 n\),空間 $n\log n $ 做法,洛谷上開O2才能過

我們先考慮對所有\(d_i< b_j\) 計算 \(j\)\(i\) 的貢獻。首先可以把詢問 \(i\) 拆成

\[\sum_{j=1}^{r_i} (a_j\oplus c_i)\le d_i - \sum_{j=1}^{l_i-1} (a_j\oplus c_i)\le d_i \]

並且和插入一起離線下來按下標的順序排好序。

那麼我們維護一個\(0-1trie\),按順序把 \(a_j\) 插入\(trie\)中,查詢就是從高到低遍歷 \(d_i\) 的每一位

如果 \(d_i\) 當前位爲0,顯然 \(trie\) 上只能走與 \(c_i\) 當前位相同的兒子。

如果 \(d_i\) 當前位爲1,對與 \(c_i\) 當前位相同的兒子 \(u0\) 進行子樹查詢 \(d_i<b_j\)\(a_j\)\(u_0\)子樹內) 的個數。因爲此時 \(c_i\)\(a_j\) 異或起來這一位比 \(d_i\) 小,後面 \(a_j\) 無論如何取值都符合條件。然後再遞歸處理與 \(c_i\) 當前位不同的兒子 \(u1\)

子樹查詢可以在\(trie\)樹上每個節點開個vector,插入的時候把 \(b_j\) 存到經過的每個節點的\(vector\)上,詢問也存在vector上,最後對於每個vector​按push進來的順序用動態開點線段樹進行插入和詢問。

\(d_i\ge b_j\) 的情況,可以當作是對每個 \(b_j\) 計算有多少個 \(b_j\le d_i\)\(c_i\oplus a_j\leq b_j\),也就是交換一下插入和詢問,按上面的做法做,然後再反過來考慮每個插入的 \(c_i,d_i\) 會被哪些詢問的 \(b_j\) 統計到。也就是在每個vector​裏把存下來的插入計算出有多少個詢問能統計到它,逆序做就行了。

由於一次插入和詢問對於trie樹上每個節點的vector最多隻會push進一個元素,每個vector最多隻有n個元素,所以每次計算完一個節點的vector的插入和詢問就清空,空間複雜度是 \(n\log n\) 的。總共有 \(n\log n\) 個元素,線段樹每次$\log n \(,時間複雜度是\)n\log^2 n$。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章