CF1902F:Trees and XOR Queries Again 题解(前缀线性基)

F:

题意:一棵树,每个点有点权,多次询问x到y的路径上的线性基能不能组成z。

Solution:

好像有很多倍增啊或者是点分治来解决线性基的合并问题的,不太想学,因为发现了一个叫前缀线性基的黑科技,只加了一个同样大小的数组,就可以用n个线性基表示任意区间的线性基。

前缀线性基模板题:CF1100F:Ivan and Burgers。就是给出序列 a,每次询问 l 到 r 的线性基能构成的最大值。

我们对于线性基的每一个数位的基向量 d[i],另外设一个 pos[i] 表示这个数位最后由谁更新,对于 lr 的询问,我们的区间线性基相当于第 r 个线性基只保留那些 pos[i]>=l 的基向量。

也就是说,我们只需要求出n个前缀线性基,然后每个前缀的每个后缀(任意区间),可以由这个前缀线性基中的 pos 数组来区分。

pos 怎么更新维护:压入一个新数字时,传入其值 x 与位置 wei ,若某个数位向量空缺,直接 d[i]=x,pos[i]=wei;若某个数位存在向量但是 pos[i]<wei ,则 swap(d[i],x);swap(pos[i],wei); 虽然不是特别好理解,但是嗯~,这么做想想不无道理。

板子代码放下面啦:

struct PLB{ int d[22], pos[22]; void insert(int x,int wei) { for(int i=21;i>=0;i--) { if(!((x>>i)&1)) continue; if(!d[i]) { d[i] = x; pos[i] = wei; return ; } if(pos[i]<wei) { swap(pos[i],wei); swap(d[i],x); } x ^= d[i]; } } int query_max(int l) { // 求最大值 int ans = 0; for(int i=21;i>=0;i--) if(d[i] && pos[i]>=l) ans = max(ans,ans^d[i]); return ans; } bool query(int k,int l) { // 能否构成k for(int i=21;i>=0;i--) { if(!(k>>i)) continue; if(!d[i] || pos[i]<l) return 0; k ^= d[i]; } return 1; } }B[N];

那么回到这道题,序列变到了树上。

每个点求出前缀线性基,即到祖先路径的线性基。

保留 x 到 lca 的线性基,就是x的前缀线性基中所有 pos>dep[lca] 的向量。再求下 y 到 lca 的线性基,两个合在一起(把一个线性基的所有向量往另一个里面塞),就是 x 到 y 路径的线性基了。

my submission


__EOF__

本文作者枫叶晴
本文链接https://www.cnblogs.com/maple276/p/17971534.html
关于博主:菜菜菜
版权声明:呃呃呃
声援博主:呐呐呐
posted @   maple276  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示