tree 逆背包

Description

白云有一棵n个结点的树,以1号结点为根,这棵树的每个结点有一个权值val i 。
定义一个连通块的喜爱度为块内所有结点权值的乘积。
白兔有很多疑问,每个疑问有两个参数k, s,表示询问所有经过点k的大小为s的连通块的喜爱度之
和。
白云会定期对树做一些修改。

input

第一行1个整数n, Q,表示树的结点个数和事件个数。
第二行n个整数表示val 1...n 。
第三行n − 1个整数表示2 . . . n号结点的父亲。
接下来Q行,第一个数为op ∈ {0, 1},如果op = 0表示白云要对某个结点的权值进行修改,接下来两
个数k, c表示把结点k的权值修改为c。如果op = 1表示白兔的疑问,接下来两个数k, s。

output

对于op = 1,每行一个数表示答案。答案对10 9 + 7取模。

数据范围

结点k的父亲为1 . . . k − 1的一个均匀随机整数。
val i ∈ [1, 10 9 + 7),s ≤ 10

solution

这题用到了树上背包的逆推
树上背包我们平时正推时:

for(int j=m;j>=1;j--)
for(int k=1;k<j;k++)
f[i][j]+=f[i][j-k]*f[son][k];

逆推我们可以:

for(int j=1;j<=m;j++)
for(int k=1;k<j;k++)
f[i][j]-=f[i][j-k]*f[son][k];
posted @ 2017-11-06 17:07  Hxymmm  阅读(299)  评论(0编辑  收藏  举报