线性基学习笔记

线性基可以维护一个数的集合,其值域为\(2^n\),那么它数组的长度为\(log_{n}\)
我们从集合里挑出一些数二进制下最高位为\(i\)的位置,然后把他放进去,数组中的每一个位置只有一个原来集合里的数,且其最高位为\(i\)。性质是原来集合每个数都可以被这个表示出来。

如何判断原集合中的数是否任意异或可以变成这个数呢?我们从高位向地位搞,如果第\(i\)位为1且线性基中没有数最高位为这个东西,那么我们就把这个东西插进去。万一线性基里没有这个数最高位为这个东西,但是这个数这一位为0呢?噢噢噢噢,我们线性基里面的数不一定要是原集合的数,还可以是原集合几个数异或起来,我们\(x\)能做到这里前面高位肯定消掉了,这样就做完了。这样我们就可以判断了。

会不会有其他的情况呢?想想正确性,如果有一个数不能被线性基,显然吧,上面也讲的很清楚了。

一个数和集合里面任意异或的最大值

从大往小做,如果\(x\)这位是0,那么从线性基里挑一个数出来,如果是1,那么就不操作
有个东西想证,就是我们这样贪心前面可能会影响到后面,会不会呢?
首先我们要保证高位最大,高位能不能通过取另外的东西来达到更大

最小值

从低位往上去,第一个是不是就是了,还要特判一下0
为什么不可能有更小的呢,如果有更小的,那么就会和这个异或,然后变成更低一位的,不合法

异或第\(k\)

我们感觉可以和那个平衡树求rank来搞一下。
我们来进行一个对线性基的重构,我们想让每一位尽可能只留下小的1,那么如果我们一个数如果后面还留下了1,那么这些位置上线性基必然没有其他数,也就是只有这么一个数,这一位上有这么一个东西,然后所以我们重构出来的线性基里面貌似是不会有位是重复的,比如\(i\)\(j\)都有\(k\)这一位,那么我们就把这两个东西异或一下,就得到了一个有\(i\)\(j\)的东西。我们先证一个东西吧,也就是线性基里面任何一个自己异或和都不为0,显然是错的吧,\(i\)\(j\)都有\(k\)这一位,那么如果我们的\(i\)最后处理没有\(k\),那么也就是说\(j\)后面\(k\)出现的次数为奇数,那么\(j\)后面可以吗。\(i\) 消不掉\(k\)代表线性基里没有\(k\)这一项,数组中只有。

重新来证吧
一个大小为n的线性基能搞出\(2^n-1\)个数,且这\(2^n-1\)个数是互不相同的,所以我们直接进行一个关于排名的映射,也就是线性基里面异或出来第\(k\)大的数就是实际的第\(k\)大。证明,我们想要做的就是就是对于异或。

好像有点像到怎么证了

我们直接设线性基里面异或第\(i\)大的数为\(ii\),第\(j\)大的数为\(jj\),(\(i\) < \(j\)),我们设\(i\)\(j\)在pos位上不同,那么\(i\){pos}就是0,\(j\)就是1,那么我们要证的就是我们异或前面的肯定比这个大,考虑我们构造的序列有什么性质,我们一个数,异或线性基里面任意一个数都会变大,所以里面异或的是那么我么前面。我们这里的\(j\)的pos只能由比较高的贡献到,而\(i\)没有贡献到,所以就证好了。结束,好难!

线性基合并

直接把一个线性基暴力插到另外一个线性基里面

一大坨题

[P3857]
直接统计线性基里面有多少位即可

[P4301]
后手胜当且仅当异或和为0,那么。错,我们现烧要构造一个集合没有子集异或和为0,还要和最小,那么就是保存在线性基里面的数和尽量大,所以我们降序排序,线性基插入的时候如果\(flag=1\)时加上就可以了

[P4570]同样的

[P11146]
摸一下交换的性质,swap(a,b)等价于a=b,b=a,a^=b
没什么用,从题目入手
首先我们要得是两个二进制数中两个数不一样才能对答案产生影响,哦,我们\(l,r\)就相当于一个\(l,r\)都是1,其他都是0的二进制数,然后最终异或完,就变成了一个操作序列,代表这个东西要不要交换,然后再和初始的搞一下,也就是和某个数异或,任选集合里的一些数,能异或出来的最大值。我们建出来线性基,然后从高往低做,然后是不是就做完了。我们可以使用一点数据结构来维护这个东西?长度为2e5的线性基,每次插入都是插一个连续的二进制数,我们先排序?然后对于起始点相同的区间,我们按末尾从后往前排序,还能搞出从末尾开始的所有东西。不太对。

有些是直接随机化建线性基了。

但是又没有方法可以log呢,先排序,我们第一次插入的时候就是一个左端点,然后一坨右端点+1,然后到了下一个。

我们对于右端点排序,然后维护每个点往右跳能挑到哪里,然后就做完了

我们这个是连续的一段
11111000000
如果已经有一段了,那么必然就是
11100000000
然后前面消掉
00011000000
然后就到了新的一个,然后这个跳就是这个意思

然后发现就假了。具体而言,我们更新后面的时候没有更新前面的,所以我们使用并查集即可。

好题!

[P3265]
实数线性基,好的。
我们类似线性基搞一下就是最高位\(i\)有东西的向量。然后就是一位一位消。

[P3292]
对于一个询问的情况,考虑对于每一条路径建立线性基

哦,这个东西是树,仔细读题啊!

那么我们把询问离线,对于\(x->y\)的路径,把\(x\)\(lca\)\(y\)\(lca\)的线性基合并。所以我们枚举\(lca\),然后有子树大小个线性基,然后启发式合并即可。

具体而言,我们使用开一个set,然后里面存的是下标,然后对应的线性基。我们把询问挂在\(lca\)上,然后对于所有询问,直接做即可。哦!但是我们怎么给所有线性基都插入呢?假!

发现这个东西瓶颈在于合并,是一个\(O(\sum size)\)的东西,考虑使用点分治优化,我们建出点分树,然后就是暴暴又力力了,直接合并即可。

有点忘记点分治的正确性了。我们点分树的性质是点分树上两点的 \(lca\) 一定在这两点在原树上的路径上。然后这题就是对的了。我们搞到点分树上的\(lca\)时挂的询问时,我们的路径一定能拆成这两个东西了。完蛋了,点分治白学了。

首先如果一个点同时是点分树内\(x\)的子树。这不是很简单吗,\(x,y\)\(lca\)\(u\),那么\(u\)里面就有两个子树分别包含\(x\)\(y\),然后路径就经过\(u\)了,所以这题就做好了。晚上开工!不会啊,难道要开线性基搞了?

哦,我写的点分治复杂度应该是对的,虽然但是错的写法树高是2log的。

对的写法

哎。想不到啊!

关于对的写法,只需在每次递归下去的时候再get一下\(siz\)即可,因为是dfs所以没有什么关系。

[P4151]
想维护到达每个点的所有路径的异或和。啊,不对。
看题解。
好像要从路径这个角度来考虑。我们一条路径必然是一条链加上一坨环,这个环可能还比较奇怪,会套来套去,就是一个大环套一个小环的情况。
首先我们线性基里面存的是所有小环的异或和,同时,我们要保证图中的所有环都能被表示出来,那么我们线性基里面的环就可能重复。不妨从dfs树的角度来考虑。对于每一条返祖边,我们\(dis[x]^dis[y]\)就代表一个环,这个是显然的。然后我们要证明对图中的每一个环都可以异或得到,显然吧!对于那种小的就是那种环什么什么烷一样的环,我们肯定统计到了,然后图中所有的环都是有这个组成的,因为异或的美妙性质,然后就做完了。
自己证点东西吧。首先我们最优的方案必然可以由图中任意一条从\(1\)\(n\)的路径得到。我们只要另选一个包含最优路径和这条路径的环(都以\(1\)开头\(n\)结尾)然后就做完了。eazy嗷。

[P3733]
最后一题。
沿用上一题的思路,就是维护图中所有环。我们新加进来的边肯定会新加进来一个环,所以就变成了线dfs一下,然后l,r时间线性基加入dis[x]dis[y]w。考虑使用线段树分治,然后就变成了线性基插入和删除一个数,不会。要吗?我们直接分治的思想是不是就做完了,就是我们每一层都存下来当前的线性基,这个时间复杂度是\(n * log_{n} *len\)的,啊?那就是可撤销线性基,这个东西简单的。

可删除线性基:
在线多个log,先讲离线。
我们已经知道每个数什么时候删除了,我们按照贪心的维护方式,肯定想在高位维护删除时间晚的东西。所以我们每插入一个数,如果这个位置上\(i\)更优了,那么我们就把线性基上这一位的数和这个数swap一下,时间也要swap,然后就做好了,我们保证了每一时刻都是最优的,这样可以少一只log。

在线,题解怎么说得这么奇怪
我们开vis数组,如果\(x\)不在线性基里面,那么直接删掉
否则我们就要找替代了
那么我们线性基,是可以删除的。
维护哪些数在线性基中,以及维护的每个线性基如何用它们表示,还有不在线性基中的数如何表示。
在插入一个数时,如果插入失败了,那么就有一个集合异或起来为0,记录为\(S\)

删除一个数x时,分类讨论。若这个数不在线性基中,直接删除即可。
否则,就要消除它的影响。如果有一个\(S\)包含\(x\)\(x\)不提供最高位,那么就用那个集合\(\oplus x\)替换\(x\),对于线性基里面所有东西都要更新一下。
如果找不到,那么说明只剩\(x\)作为最高位的集合了,我们将这个集合异或\(x\),然后重新插入即可。
code
不想写了

posted @ 2025-07-09 10:17  wuhupai  阅读(20)  评论(0)    收藏  举报