LG P5127 子异和 Solution

Description

对于序列 a a a,设 f ( a ) f(a) f(a) a a a 的所有非空子序列的 xor ⁡ \operatorname{xor} xor 和之和。
给你一棵 n n n 个点的树 T T T,每个点有点权 w i w_i wi,你需要执行 q q q 次操作,操作分两种:

  • 1 u v:设 a a a u → v u\to v uv 路径上的所有点权构成的序列,求 f ( a )   m o d   ( 1 0 9 + 7 ) f(a)\bmod (10^9+7) f(a)mod(109+7)
  • 2 u v k:对于 u → v u\to v uv 路径上的每个点 x x x 执行 w x ← w x xor ⁡ k w_x\gets w_x\operatorname{xor}k wxwxxork

Limitations

1 ≤ n , q ≤ 2 × 1 0 5 1\le n,q\le 2\times 10^5 1n,q2×105
1 ≤ u , v ≤ n 1\le u,v\le n 1u,vn
0 ≤ a i , k ≤ 1 0 9 + 7 0\le a_i,k\le 10^9+7 0ai,k109+7
1 s , 125 MB 1\text{s},125\text{MB} 1s,125MB

Solution

根据 P5390,可以得到 f ( a ) = ( or ⁡ i = 1 t a i ) × ( 2 t − 1 ) f(a)=(\operatorname{or}_{i=1}^{t} a_i)\times (2^t-1) f(a)=(ori=1tai)×(2t1),其中 t t t a a a 的长度。
现在问题转化为:链上 xor ⁡ \operatorname{xor} xor 一个数,链上 or ⁡ \operatorname{or} or 和,直接树剖拍到序列上。

接下来考虑序列上的问题,用线段树维护,每个节点存储两个整数 p , q p,q p,q,其中 p p p 表示所管辖区间的 and ⁡ \operatorname{and} and 和(即每位是否全 1 1 1), q q q 表示区间所有数取反后的 and ⁡ \operatorname{and} and 和(即每位是否全 0 0 0),那么答案就是 q q q 取反后的值。

对于修改,考虑实际意义,对于 p p p,新的全 1 1 1 位显然包含翻转过的全 0 0 0 位和未翻转的全 1 1 1 位, q q q 同理,代码如下(一定要用 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 ( q log ⁡ 2 n ) O(q\log^2 n) O(qlog2n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值