2024.7 #4 華夏風華 琢一番飛揚 待得開拓封疆 濟滄桑 遊目聘懷森森永珍 瀝肝膽 披閱九州的 風光

sqrtqwq發表於2024-07-30

華夏風華 琢一番飛揚
待得開拓封疆 濟滄桑
遊目聘懷森森永珍 瀝肝膽
披閱九州的 風光


1. P7470 [NOI Online 2021 提高組] 島嶼探險

我們可以發現這個東西可以拆成很多個子問題,然後累計合併,這個東西可以使用線段樹合併來做。

先考慮 \(b_i > d_j\) 的情況。那麼答案就是 \(\sum [a_i \oplus c_j \le d_j]\)。我們把 \(a_i\) 插入 \(01 \text{trie}\) 中。然後我們從上往下走,走到深度為 \(h\) 的節點,那麼代表他的值等於 \(c_i \oplus d_j\) 的前 \(h\) 位。然後我們考慮第 \(h + 1\) 位。

  • \(d_i = 0\),那麼 \(a_i\)\(c_j\) 的第 \(h + 1\) 位必須相等,否則 \(a_i \oplus c_j > d_j\),然後直接往這個方向走即可。

  • \(d_i = 1\),那麼此時 \(a_i\)\(c_j\) 的第 \(h + 1\) 位任意取都行。那麼就有兩種可能:

    • 如果 \(a_i\)\(c_j\) 的第 \(h + 1\) 位不一樣,那麼此時 \(a_i\) 依然等於 \(c_j \oplus d_j\),所以我們向這個方向繼續走即可。
    • 如果 \(a_i\)\(c_j\) 的第 \(h + 1\) 位一樣,那麼此時 \(a_i \oplus c_j\) 就會一定小於 \(d_j\) 了,那麼對於答案的貢獻就是這個子樹裡 \(a_i\) 的個數之和。

這一部分就是 CF817E。比較簡單。

接下來我們考慮 \(b_i \le d_j\) 的情況。這一個部分比較困難。但是我們發現這一個部分和 \(a_i \oplus c_j \le d_j\) 的結構很像,所以我們可以考慮類似的操作。

前面的是對於 \(a_i\) 扔到 \(01 \text{trie}\) 上然後查詢 \((c_j,d_j)\),那麼我們這次就可以把 \(c_j\) 扔到 \(01 \text{trie}\) 上,然後記錄每一個 \((a_i,b_i)\) 對於 \(c_j\) 的貢獻。

具體的我們只需要把 \(c_j\) 離線下來,然後對於 \((a_i,b_i)\) 查詢,但是唯一的區別就是在上面我們遇到了一個節點滿足 \(a_i \oplus c_j < d_j\) 時我們加上的是子樹裡 \(a_i\) 的個數和,而現在我們要在這一個子樹打一個標記,讓整一個子樹全部都加上 \(1\),然後統計答案是就是從根到 \(c_j\) 路徑上的標記和。

當然我們不能每一次都建 \(2\)\(01 \text{trie}\),但是那樣子的複雜度爆炸,無法接受。

然後我們考慮如何優雅的計算多組資料。

首先我們將 \((a_i,b_i)\)\((c_j,d_j)\) 按照 \(b_i,d_j\) 升序排列。然後那雙指標進行維護。此時我們開兩個 \(01 \text{trie}\)。然後當我們掃到了第 \(j\) 個問題不滿足 \(b_j > d_j\)\(a_i\) 從維護第一個 \(01 \text{trie}\) 中刪除,然後計算貢獻。同時對於滿足條件的 \((a_i,b_i)\) 加入維護第二個情況的 \(01 \text{trie}\) 上並且計算貢獻。

當然此時兩個指標都往右移動。

相關文章