CF1100F Ivan and Burgers 题解
题意
一个长为 \(n\) 序列, \(q\) 次询问,每次询问一个区间 [\(l,r]\) 内的最大异或和.
\(n,q \le 5e5\)
题解
最大异或和 很容易想到 线性基,问题转化为 维护区间线性基
然而如果我们用线段树去维护,那么合并只能暴力和并,复杂度 \(log^3\) .
我们考虑 按顺序单个地 往线性基里插元素,那么问题转化为 维护后缀线性基 。
考虑 insert 操作,通常我们每次是让早出现的元素占据高位,现在为了让晚出现的贡献尽量大,需要 晚出现的放到高位 ,所以对于可以更新的行,我们保留原序列中位置靠后的元素 ,把位置靠前的元素异或后往下更新。
这其实相当于先插入位置靠后的,然后再插入位置靠前的元素。虽然线性基里的元素不是原序列里的元素,但是线性基可以表出所有原序列可以表出的元素,所以 插入线性基里的元素就等同于插入原序列里的元素 。
我们还可以考虑每个元素插入线性基的过程:它只会更新之前的元素,而自己不会被异或,相当于每个线性基里的元素都只会被后面插入的元素异或一部分后往下更新,即相当于从后往前插元素,自然也保证了是后缀线性基
核心代码
inline void insert(int x,int id){
for(ri i = 20;i >= 0;--i)
if(x & (1<<i)){
if(!val[i]){
val[i] = x,pos[i] = id;
return;
}
if(pos[i] < id) swap(x,val[i]),swap(id,pos[i]);
x ^= val[i];
}
}