LG P5127 子异和 Solution
Description
对于序列 aaa,设 f(a)f(a)f(a) 为 aaa 的所有非空子序列的 xor\operatorname{xor}xor 和之和。
给你一棵 nnn 个点的树 TTT,每个点有点权 wiw_iwi,你需要执行 qqq 次操作,操作分两种:
1 u v
:设 aaa 为 u→vu\to vu→v 路径上的所有点权构成的序列,求 f(a)mod(109+7)f(a)\bmod (10^9+7)f(a)mod(109+7)。2 u v k
:对于 u→vu\to vu→v 路径上的每个点 xxx 执行 wx←wxxorkw_x\gets w_x\operatorname{xor}kwx←wxxork。
Limitations
1≤n,q≤2×1051\le n,q\le 2\times 10^51≤n,q≤2×105
1≤u,v≤n1\le u,v\le n1≤u,v≤n
0≤ai,k≤109+70\le a_i,k\le 10^9+70≤ai,k≤109+7
1s,125MB1\text{s},125\text{MB}1s,125MB
Solution
根据 P5390,可以得到 f(a)=(ori=1tai)×(2t−1)f(a)=(\operatorname{or}_{i=1}^{t} a_i)\times (2^t-1)f(a)=(ori=1tai)×(2t−1),其中 ttt 为 aaa 的长度。
现在问题转化为:链上 xor\operatorname{xor}xor 一个数,链上 or\operatorname{or}or 和,直接树剖拍到序列上。
接下来考虑序列上的问题,用线段树维护,每个节点存储两个整数 p,qp,qp,q,其中 ppp 表示所管辖区间的 and\operatorname{and}and 和(即每位是否全 111),qqq 表示区间所有数取反后的 and\operatorname{and}and 和(即每位是否全 000),那么答案就是 qqq 取反后的值。
对于修改,考虑实际意义,对于 ppp,新的全 111 位显然包含翻转过的全 000 位和未翻转的全 111 位,qqq 同理,代码如下(一定要用 unsigned
,这样取反才是对的):
struct tag {unsigned x;inline tag() : x(0) {}inline tag(unsigned x) : x(x) {}inline void apply(const tag& t) { x ^= t.x; }
};struct info {unsigned one, zero;inline info() : one(0), zero(0) {}inline info(unsigned one, unsigned zero) : one(one), zero(zero) {}inline void apply(const tag& t) {*this = *this ^ t.x;}inline info operator^(unsigned x) const {return {(one & ~x) | (zero & x), (zero & ~x) | (one & x)};}inline info operator+(const info& b) const {return {one & b.one, zero & b.zero};}
};
那么这题就做完了,完整代码不给了,时间复杂度 O(qlog2n)O(q\log^2 n)O(qlog2n)。