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 u→v 路径上的所有点权构成的序列,求 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 u→v 路径上的每个点 x x x 执行 w x ← w x xor k w_x\gets w_x\operatorname{xor}k wx←wxxork。
Limitations
1
≤
n
,
q
≤
2
×
1
0
5
1\le n,q\le 2\times 10^5
1≤n,q≤2×105
1
≤
u
,
v
≤
n
1\le u,v\le n
1≤u,v≤n
0
≤
a
i
,
k
≤
1
0
9
+
7
0\le a_i,k\le 10^9+7
0≤ai,k≤109+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)×(2t−1),其中
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)。
25万+

被折叠的 条评论
为什么被折叠?



