线性基学习记录
我对线性基的理解并不是很深...(其实是不怎么会)...学习的时候参照了ljh2000的博客。下面会提到线性基解决的问题,如何构造和合并,最基本的查询。
线性基可以解决的问题:求一些数的异或和最大,支持加入元素,插入一个数x的复杂度是logx,查询一次的复杂度也是log(查询指查询xor最大值或是一个数能否被异或出)。
线性基可以看成是把n个数a1,a2...an,映射到一个大小是log(max)的集合上。通过已经构造好的线性基可以xor出与原来数集xor出的值域相同。
构造线性基,插入的数是x,二进制下第i位的线性基是a[i]。从高到低逐位扫x,如果第i位是0就跳过不管;如果是1并且a[i]=0,那么就把当前x作为a[i],否则就把x异或上这一位的线性基(x=x xor a[i])。然后接着往后扫。
如果要查异或最大值,直接从高到低位贪心,如果异或上这一位的线性基可以使答案变大,就异或。(正确性显然?)
查询一个数x能否被异或出,从高到低位扫,如果x这一位是1,就异或上当前位的线性基,如果中途x变成了0,那就说明x可以被异或得到。(类似插入)
线性基合并就直接把两个线性基暴力合并(把其中一个线性基,当成是新的数字暴力插到另一个线性基就可以了,正确性显然...)
查询第k小,将k二进制拆分,k的当前位是1就异或对应位的线性基。那么第k大呢..?
刚刚想到第k大的第一想法竟然是不可做...首先考虑一共能异或出多少种数,一共能异或出2^n个不同的数,n是线性基不为0的个数。那么第k大就是第(2^n-k+1)小...问题解决...
好像有点空洞...马上就补道题2333...