筆記-字首線性基
阿新 • • 發佈:2022-06-05
正文
其實是個很 simple 的東西。
考慮這樣一個問題
對於一個數列,求 \([l,r]\) 中的數的異或最大值,強制線上。
如果 \([l,r]\) 是全集那麼我們很容易使用線性基得到答案,考慮線上段樹上維護線性基,但是這顯然很蠢(複雜度會多一個 \(\log{n}\))。
考慮對每個 \(i\) 維護 \([1,i]\) 倒著插入的線性基,簡單來說就是我們想要儘可能考慮 \(i\) 的數作為基。這並不需要真的倒著插入,只需在從前往後加入每個 \(i\) 的時候貪心判斷即可。
具體的流程
-
複製 \(i-1\) 的線性基
-
將 \(a[i]\) 插入
-
插入時如果該位置已經有值,替換成 \(a[i]\)
struct Linear_Base{ int a[31][2]; void insert(int x, int pos) { for (int i = 30; i >= 0; i--) { if (x & (1 << i)) { if (!a[i][0]) { a[i][0] = x; a[i][1] = pos; break; } else { if (a[i][1] < pos) swap(a[i][0], x), swap(a[i][1], pos); x ^= a[i][0]; } } } } }xxj[maxn];
考慮查詢,如果對於某一位最近的都比 \(l\) 小,那麼我們就不能使用這一位。例查詢最大值:
for (int i = 30; i >= 0; i--) {
if (xxj[r].a[i][1] >= l) {
if ((ans ^ xxj[r].a[i][0]) > ans) {
ans ^= xxj[r].a[i][0];
}
}
}
習題
luogu3292(比什麼點分治香多了)