链接:https://www.nowcoder.com/acm/contest/57/F

时间限制:C/C++ 2秒,其他语言4秒

空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描

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

输入描述:

第一行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。
 

输出描述:

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

输入例子:
15 15
6 4 8 6 8 9 10 9 2 9 8 3 3 6 2
1 1 1 3 1 3 6 5 3 10 9 7 9 13
1 13 8
1 2 4
1 12 8
1 11 2
0 2 9
0 11 4
1 3 6
0 4 5
1 13 7
1 8 2
1 7 6
1 7 8
0 5 5
0 1 7
1 1 6
输出例子:
128592000
11304
35520768
72
10402608
16325280
81
6030720
359079840
8686888

-->

示例1

输入

15 15
6 4 8 6 8 9 10 9 2 9 8 3 3 6 2
1 1 1 3 1 3 6 5 3 10 9 7 9 13
1 13 8
1 2 4
1 12 8
1 11 2
0 2 9
0 11 4
1 3 6
0 4 5
1 13 7
1 8 2
1 7 6
1 7 8
0 5 5
0 1 7
1 1 6

输出

128592000
11304
35520768
72
10402608
16325280
81
6030720
359079840
8686888

备注:

结点k的父亲为1...k-1的一个均匀随机整数。
vali∈[1,109+7),s≤10,n,Q≤10^5
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
题解:

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 #include <bits/stdc++.h>
#define mst(a,b) memset((a),(b), sizeof a)
#define lowbit(a) ((a)&(-a))
#define IOS ios::sync_with_stdio(0);cin.tie(0);
#define MP make_pair
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+;
const int maxn=1e5+;
ll dp[maxn][];
int val[maxn],fa[maxn];
vector<int>son[maxn];
int qpow(ll a,int b){
ll res=;
while(b){
if(b&)res=res*a%mod;
b>>=;
a=a*a%mod;
}
return res;
}
void add(int a,int b){
for(int i=;i;--i)
for(int j=;j<i;++j)
dp[a][i]=(dp[a][i]+dp[b][j]*dp[a][i-j])%mod; }
void del(int a,int b){
for(int i=;i<=;++i)
for(int j=;j<i;++j)
dp[a][i]=(dp[a][i] - dp[b][j]*dp[a][i-j])%mod;
}
void dfs(int pos){
dp[pos][]=;dp[pos][]=val[pos];
for(int i=;i<son[pos].size();++i){
int to=son[pos][i];
dfs(to);
add(pos,to);
}
}
void update_1(int pos){
if(pos==)return;
update_1(fa[pos]);
del(fa[pos],pos);
}
void update_2(int pos){
if(pos==)return;
add(fa[pos],pos);
update_2(fa[pos]);
}
void update(int k,int c){
update_1(k);
int cc=qpow(val[k],mod-);
for(int i=;i<=;++i)
dp[k][i]=dp[k][i]*cc%mod*c%mod;
val[k]=c;
update_2(k);
}
ll dd[][];
int now;
void qq(int pos,int s){
if(pos!=)qq(fa[pos],pos);
now^=;
memcpy(dd[now],dp[pos],sizeof dp[pos]);
for(int i=;i<=;++i)
for(int j=;j<i;++j)
dd[now][i]=(dd[now][i] - dp[s][j]*dd[now][i-j])%mod;
if(pos!=){
for(int i=;i;--i)
for(int j=;j<i;++j)
dd[now][i]=(dd[now][i]+dd[now^][j]*dd[now][i-j])%mod;
}
}
int query(int k,int s){
if(k==)return (dp[k][s]+mod)%mod;
int f=fa[k];
qq(f,k);
ll ret=;
for(int i=;i<s;++i)
ret=(ret+dd[now][i]*dp[k][s-i])%mod;
return (ret+mod)%mod;
}
int main(){
#ifdef local
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
int n,q;scanf("%d%d",&n,&q);
for(int i=;i<=n;++i)scanf("%d",&val[i]);
for(int i=;i<=n;++i){
scanf("%d",&fa[i]);
son[fa[i]].push_back(i);
}
dfs();
while(q--){
int op,a,b;scanf("%d%d%d",&op,&a,&b);
if(op)printf("%d\n",query(a,b));
else update(a,b);
}
return ;
}

首先是随机树的树高是logn这点是不知道的,所以看到题就是蒙圈的,这点是学到了

然后在码的过程中update那个函数,里面对于k点dp值的更新我一开始是这样的

   for(int i=;i<=;++i){
dp[k][i]=(dp[k][i]-val[k]*dp[k][i-])%mod;
dp[k][i]=(dp[k][i]+mod)%mod;
}
val[k]=c;
for(int i=;i;--i){
dp[k][i]=(dp[k][i]+dp[k][i-]*val[k])%mod;
}

错的很离谱,引以为鉴

wannalfy 挑战赛8 F 白云的树(树形dp)的更多相关文章

  1. 牛客挑战赛30 小G砍树 树形dp

    小G砍树 dfs两次, dp出每个点作为最后一个点的方案数. #include<bits/stdc++.h> #define LL long long #define fi first # ...

  2. wannalfy 挑战赛7 F Masha与老鼠(贪心+dp)

    链接:https://www.nowcoder.net/acm/contest/56/F   时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K 6 ...

  3. 【BZOJ-3572】世界树 虚树 + 树形DP

    3572: [Hnoi2014]世界树 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1084  Solved: 611[Submit][Status ...

  4. 【BZOJ-2286】消耗战 虚树 + 树形DP

    2286: [Sdoi2011消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2120  Solved: 752[Submit][Status] ...

  5. bzoj 2286(虚树+树形dp) 虚树模板

    树链求并又不会写,学了一发虚树,再也不虚啦~ 2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5002  Sol ...

  6. 洛谷 P1453 城市环路 ( 基环树树形dp )

    题目链接 题目背景 一座城市,往往会被人们划分为几个区域,例如住宅区.商业区.工业区等等.B市就被分为了以下的两个区域--城市中心和城市郊区.在着这两个区域的中间是一条围绕B市的环路,环路之内便是B市 ...

  7. BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP+树剖lca

    BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的 ...

  8. 51nod 1353 树 | 树形DP经典题!

    51nod 1353 树 | 树形DP好题! 题面 切断一棵树的任意条边,这棵树会变成一棵森林. 现要求森林中每棵树的节点个数不小于k,求有多少种切法. 数据范围:\(n \le 2000\). 题解 ...

  9. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

随机推荐

  1. Luogu P3953 [NOIP2017]逛公园

    题目 首先我们跑出从\(1\)出发的最短路\(d1\)和反图上从\(n\)出发的最短路\(dn\). 然后我们处理出长度不超过\(d1_n+k\)的最短路边集,给它拓扑排序. 如果存在环,那么这个环一 ...

  2. 认识react, 并简单与vue对比

    应用场景: 负责场景下的高性能 重用组件库,组件组合 中文官网:https://reactjs.org.cn/doc/in... 特点: 声明式编码(不需要关心如何实现,只需要关注在哪里做什么) 组件 ...

  3. php开发环境推荐使用

    万丈高楼平地起,好用得环境才能建立宏伟大厦,php开发环境推荐使用 1,自己安装 lamp 环境 linux+apache+mysql+php 2,自己安装 lnmp 环境 linux+nginx+m ...

  4. UnknownPropertyException(Yii2)

    在class里面的rule有属性,但是没声明

  5. 利用wampserve搭建本服务器

    1.官网下载安装包 注意:3.0.6版本需要下载依赖包vc依赖包 2.默认为英文 右击图标进入langue设置为中文 3.需要手动设置在现状态 右击=>选中wampsetting =>me ...

  6. ABAP中TAB分隔符的使用

    在ABAP开发中,存在很多特殊字符,使用情况也不同,下面及时SAP中的TAB分隔符的使用案例: 46C以下的版本: DATA: gc_result(50) type c. constants: con ...

  7. :OpenCV人脸识别Fisherface算法源码分析

    https://blog.csdn.net/loveliuzz/article/details/73875904

  8. C语言:标准IO_fopen( )、fclose() ①

    思前想后一个月,我终于敲下了我的第一篇开山之作. 博客千千万,我的博客首先记录的是学习时候的理解,用于给自己翻阅查找,现在主要研究的是C语言和STM32.如果能帮到你,那是最好的,假如我写的东西有错误 ...

  9. RBAC | YAML |

    YAML配置文件: 1.凡是可以在application.properties配置的文件,都可以在application.yaml文件中配置 2.properties的优先级大于yaml的优先级 后端 ...

  10. Linux查看某进程的线程

    首先得知道你要查的进程的PID: 比如我要查看看我unimrcpserver的线程 第二种方法:top top命令可以实时显示各线程情况.就相当于windows的资源管理器.