Description 题目描述
Chavo有一颗水晶树,树上会结出魔法水晶。包括树根在内,树一共有 n n n个分叉的节点,其中 1 1 1号节点为树根,初始状态下每一个节点都有一个生长值 a i a_i ai。Chavo有一根法杖,法杖可以对某个节点 u u u释放生长法术,使得以 u u u为根的子树的每个节点的生长值更新为 f ( k ) f(k) f(k)。对于每一个被更新的节点来说, f ( x ) f(x) f(x)的定义都不一样,其中 f ( 1 ) f(1) f(1)是在释放法术之前被更新节点的生长值, f ( 2 ) f(2) f(2)是在释放法术之前节点 v v v的生长值。但是对于所有被更新的节点来说, f ( x ) f(x) f(x)的递推公式都一样,是 f ( x ) = f ( x − 1 ) + f ( x − 2 ) + k f(x)=f(x-1)+f(x-2)+k f(x)=f(x−1)+f(x−2)+k。Chavo想要释放 m m m次生长法术,每次法术都给定 u , v , k u,v,k u,v,k,她想问问你释放法术之后所有节点的生长值的和是多少?结果要对 1000000007 1000000007 1000000007取模后输出。
Input 输入
第一行输入整数 n n n和 m m m
第二行输入 n n n个整数,第 i i i个整数代表第 i i i个节点上初始值 a i a_i ai
接下来 n − 1 n-1 n−1行,每一行有两个正整数 i , j i,j i,j,代表树上第 i i i个节点和第 j j j个节点有树杈相连。
接下来 m m m行,每一行有 3 3 3个正整数 u , v , k u,v,k u,v,k,如题目描述
Output 输出
输出一个整数代表经过所有操作后整棵树上所有节点数的和,结果要对 1000000007 1000000007 1000000007取模后输出。
Sample Input 样例输入
3 2
3 4 5
1 2
1 3
1 2 2
2 3 3
Sample Output 样例输出
19
Limits 限制
对于 30 % 30\% 30%的数据, 1 ≤ n , m , k ≤ 100 , 1 ≤ u , v , i , j ≤ n , 0 ≤ a i ≤ 100 1≤n,m,k≤100,1≤u,v,i,j≤n,0≤a_i≤100 1≤n,m,k≤100,1≤u,v,i,j≤n,0≤ai≤100
对于 60 % 60\% 60%的数据, 1 ≤ n , m ≤ 1 0 3 , 1 ≤ k ≤ 1 0 9 , 1 ≤ u , v , i , j ≤ n , 0 ≤ a i ≤ 1 0 9 1≤n,m≤10^3,1≤k≤10^9,1≤u,v,i,j≤n,0≤a_i≤10^9 1≤n,m≤103,1≤k≤109,1≤u,v,i,j≤n,0≤ai≤109
对于 100 % 100\% 100%的数据,$1≤n,m≤105,1≤k≤109,1≤u,v,i,j≤n,0≤a_i≤10^9 $
Time Limit : 2 s 2s 2s & Memory Limit : 128 M B 128MB 128MB
Hints 提示
第一次操作时,更新 1 、 2 、 3 1、2、3 1、2、3号点,对于 1 1 1号点, f ( 1 ) = 3 , f ( 2 ) = 4 f(1)=3,f(2)=4 f(1)=3,f(2)=4,更新后 1 1 1号点值为 f ( 2 ) = 4 f(2)=4 f(2)=4,同理 2 、 3 2、3 2、3号点值为 4 4 4
第二次操作时,更新 2 2 2号点, f ( 1 ) = 4 , f ( 2 ) = 4 , f ( 3 ) = 11 f(1)=4,f(2)=4,f(3)=11 f(1)=4,f(2)=4,f(3)=11,更新后 2 2 2号点为 11 11 11
最后求和为 4 + 11 + 4 = 19 4+11+4=19 4+11+4=19
注意,
f
(
1
)
f(1)
f(1)是对于子树内每个点说的……每个点的
f
(
1
)
f(1)
f(1)不一定相同,不过都是该点的权值。
树上实现子树修改和查询,搞出来个DFS序就变成了区间问题,线段树即可解决。
但是这什么鬼畜修改。类似于斐波那契数列的递推关系,可以考虑构造矩阵,做矩阵快速幂。
先看看
f
(
x
)
f(x)
f(x)的一些值有什么规律:
f ( 1 ) = u f ( 2 ) = v f ( 3 ) = u + v + k f ( 4 ) = u + 2 v + k f ( 5 ) = 2 u + 3 v + 4 k f ( 6 ) = 3 u + 5 v + 7 k f ( 7 ) = 5 u + 8 v + 12 k … \begin{aligned} f(1)&=u\\ f(2)&=v\\ f(3)&=u+v+k\\ f(4)&=u+2v+k\\ f(5)&=2u+3v+4k\\ f(6)&=3u+5v+7k\\ f(7)&=5u+8v+12k\\ &\dots \end{aligned} f(1)f(2)f(3)f(4)f(5)f(6)f(7)=u=v=u+v+k=u+2v+k=2u+3v+4k=3u+5v+7k=5u+8v+12k…
如果我们定义一个类斐波那契数列
F
i
F_i
Fi,
F
−
1
=
1
,
F
0
=
0
,
F
1
=
1
F_{-1}=1,F_0=0,F_1=1
F−1=1,F0=0,F1=1,
F
i
=
F
i
−
1
+
F
i
−
2
(
i
>
1
)
F_i=F_{i-1}+F_{i-2}\ \ \ \ (i>1)
Fi=Fi−1+Fi−2 (i>1),
f
(
T
)
f(T)
f(T)就可以这样描述了:
f
(
T
)
=
F
T
−
2
u
+
F
T
−
1
v
+
(
F
T
−
1
)
k
f(T)=F_{T-2}u+F_{T-1}v+(F_T-1)k
f(T)=FT−2u+FT−1v+(FT−1)k
怎么构造矩阵呢?
可以分为两种矩阵,线段树里的矩阵和处理影响的矩阵。
线段树里的矩阵,叶子节点的
S
S
S这样构造:
S
=
[
u
0
1
0
0
0
0
0
0
]
S= \begin{bmatrix} u&0&1\\ 0&0&0\\ 0&0&0\\ \end{bmatrix}
S=⎣⎡u00000100⎦⎤
其中,
u
u
u为此时这个节点的权值。
非叶子节点的
S
S
S为单位矩阵。
处理影响的矩阵
T
T
T是两个矩阵的乘积:
T
=
[
1
0
0
0
0
0
0
v
1
]
×
[
0
1
0
1
1
0
0
k
1
]
k
−
1
T= \begin{bmatrix} 1&0&0\\ 0&0&0\\ 0&v&1\\ \end{bmatrix} \times \begin{bmatrix} 0&1&0\\ 1&1&0\\ 0&k&1\\ \end{bmatrix} ^{k-1}
T=⎣⎡10000v001⎦⎤×⎣⎡01011k001⎦⎤k−1
其中,
v
v
v是节点
v
v
v的生长值,
k
k
k意义与题中相同。
那么这么乘能乘出来些什么?
为了方便,令:
A
=
[
0
1
1
1
1
0
0
k
1
]
,
B
=
[
1
0
0
0
0
0
0
v
1
]
A= \begin{bmatrix} 0&1&1\\ 1&1&0\\ 0&k&1\\ \end{bmatrix} ,B= \begin{bmatrix} 1&0&0\\ 0&0&0\\ 0&v&1\\ \end{bmatrix}
A=⎣⎡01011k101⎦⎤,B=⎣⎡10000v001⎦⎤
发现
A
c
A^c
Ac这个矩阵是这样的:
A
c
=
[
F
c
−
1
F
c
0
F
c
F
c
+
1
0
(
F
c
+
1
−
1
)
k
(
F
c
+
2
−
1
)
k
1
]
A^c= \begin{bmatrix} F_{c-1}&F_c&0\\ F_c&F_{c+1}&0\\ (F_{c+1}-1)k&(F_{c+2}-1)k&1\\ \end{bmatrix}
Ac=⎣⎡Fc−1Fc(Fc+1−1)kFcFc+1(Fc+2−1)k001⎦⎤
那么,
A
k
−
1
A^{k-1}
Ak−1就是这样的:
A
k
−
1
=
[
F
k
−
2
F
k
−
1
0
F
k
−
1
F
k
0
(
F
k
−
1
)
k
(
F
k
+
1
−
1
)
k
1
]
A^{k-1}= \begin{bmatrix} F_{k-2}&F_{k-1}&0\\ F_{k-1}&F_{k}&0\\ (F_k-1)k&(F_{k+1}-1)k&1\\ \end{bmatrix}
Ak−1=⎣⎡Fk−2Fk−1(Fk−1)kFk−1Fk(Fk+1−1)k001⎦⎤
B
×
A
k
−
1
B\times A^{k-1}
B×Ak−1就是这样的:
B
×
A
k
−
1
=
[
F
k
−
2
F
k
−
1
0
0
0
0
v
F
k
−
1
+
(
F
k
−
1
)
k
v
F
k
+
(
F
k
+
1
−
1
)
k
1
]
B\times A^{k-1}= \begin{bmatrix} F_{k-2}&F_{k-1}&0\\ 0&0&0\\ vF_{k-1}+(F_k-1)k&vF_k+(F_{k+1}-1)k&1\\ \end{bmatrix}
B×Ak−1=⎣⎡Fk−20vFk−1+(Fk−1)kFk−10vFk+(Fk+1−1)k001⎦⎤
更新一个叶子节点后,叶节点的矩阵就是这样的:
S
×
B
×
A
k
−
1
=
[
u
F
k
−
2
+
v
F
k
−
1
+
(
F
k
−
1
)
k
u
F
k
−
1
+
v
F
k
+
(
F
k
+
1
−
1
)
k
1
0
0
0
0
0
0
]
S\times B\times A^{k-1}= \begin{bmatrix} uF_{k-2}+vF_{k-1}+(F_k-1)k&uF_{k-1}+vF_k+(F_{k+1}-1)k&1\\ 0&0&0\\ 0&0&0\\ \end{bmatrix}
S×B×Ak−1=⎣⎡uFk−2+vFk−1+(Fk−1)k00uFk−1+vFk+(Fk+1−1)k00100⎦⎤
u
u
u的位置顺利被
f
(
k
)
f(k)
f(k)替代,构造成功。
那么,如何更新答案?
对于线段树矩阵,更新一个区间时
S
S
S矩阵乘
T
T
T
每次查询节点
v
v
v的生长值时,将这一区间矩阵下传,之后清为单位矩阵。
最后,将线段树上非叶子节点全部下传清为单位矩阵后,统计答案。
即将
S
S
S矩阵中的
u
u
u加起来。
Code
总时间复杂度为
O
(
m
(
log
2
n
+
log
2
k
)
)
O(m(\log_2 n+\log_2 k))
O(m(log2n+log2k))