[省选] [线段树] [DFS序] [矩阵快速幂] [HLOI2015] Tree

14 篇文章 0 订阅
1 篇文章 0 订阅

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(x1)+f(x2)+k。Chavo想要释放 m m m次生长法术,每次法术都给定 u , v , k u,v,k uvk,她想问问你释放法术之后所有节点的生长值的和是多少?结果要对 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 n1行,每一行有两个正整数 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 1n,m,k100,1u,v,i,jn,0ai100
对于 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 1n,m103,1k109,1u,v,i,jn,0ai109
对于 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 123号点,对于 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 23号点值为 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 F1=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=Fi1+Fi2    (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)=FT2u+FT1v+(FT1)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×01011k001k1
其中, 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=Fc1Fc(Fc+11)kFcFc+1(Fc+21)k001
那么, A k − 1 A^{k-1} Ak1就是这样的:
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} Ak1=Fk2Fk1(Fk1)kFk1Fk(Fk+11)k001
B × A k − 1 B\times A^{k-1} B×Ak1就是这样的:
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×Ak1=Fk20vFk1+(Fk1)kFk10vFk+(Fk+11)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×Ak1=uFk2+vFk1+(Fk1)k00uFk1+vFk+(Fk+11)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))

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值