華夏風華 琢一番飛揚
待得開拓封疆 濟滄桑
遊目聘懷森森永珍 瀝肝膽
披閱九州的 風光
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}\) 上並且計算貢獻。
當然此時兩個指標都往右移動。