1. 程式人生 > 其它 >筆記-字首線性基

筆記-字首線性基

正文

其實是個很 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];
        }
    }
}

習題

CF1100F

hdu6579

luogu3292(比什麼點分治香多了)

hdu6845