原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round2-E.html

题目传送门 - 2018牛客多校赛第二场 E

题意

  一棵 $n$ 个结点的树,每个点有一个点权,有 $m$ 次操作,每次操作有三种:

  1.  修改一个点的点权

  2.  修改一个点的父亲

  3.  询问包含某个点的所有大小为 $c$ 的连通块的点权乘积之和。

  $n,m\leq 100000,c\leq10 $

题解

    

  

  
  以上题解图片摘自 laofu 题解。

  我再画几幅图介绍一下:

  注:箭头表示箭头尾端节点的 dp 对箭头指向节点有 dp 贡献。

    虚箭头表示中间省略一些有箭头连接的节点。

    虚线表示中线省略一些节点,但是没有箭头连接。

    每个图,最上面的节点表示往上走 $10$ 步到达的祖先。

    最下面的节点表示操作中的 $x$ 节点。

    注意一下修改和询问里面各有一个特殊箭头,意义自己理解。

  

  

代码

#include <bits/stdc++.h>
using namespace std;
int read(){
char ch=getchar();
int x=0;
while (!isdigit(ch))
ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+ch-48,ch=getchar();
return x;
}
const int N=100005,mod=1e9+7;
int n,m,val[N],fa[N];
int dp[N][11];
int Pow(int x,int y){
int ans=1;
for (;y;y>>=1,x=1LL*x*x%mod)
if (y&1)
ans=1LL*ans*x%mod;
return ans;
}
void DP(int a,int b){
if (!a||!b)
return;
for (int i=10;i>=1;i--)
for (int j=1;j<i;j++)
dp[a][i]=(1LL*dp[a][i]+1LL*dp[a][j]*dp[b][i-j])%mod;
}
void IDP(int a,int b){
if (!a||!b)
return;
for (int i=1;i<=10;i++)
for (int j=1;j<i;j++)
dp[a][i]=(1LL*dp[a][i]-1LL*dp[a][j]*dp[b][i-j])%mod;
}
int main(){
n=read(),m=read();
memset(dp,0,sizeof dp);
for (int i=1;i<=n;i++)
dp[i][1]=val[i]=read();
for (int i=2;i<=n;i++)
fa[i]=read();
for (int i=n;i>1;i--)
DP(fa[i],i);
while (m--){
int opt=read(),x=read(),y=read(),anc[15];
if (opt==0){
for (int i=1,j=x;i<=10;i++,j=fa[j])
anc[i]=j;
for (int i=10;i>1;i--)
IDP(anc[i],anc[i-1]);
int inv=Pow(val[x],mod-2);
val[x]=y;
for (int i=1;i<=10;i++)
dp[x][i]=1LL*dp[x][i]*inv%mod*y%mod;
for (int i=1;i<10;i++)
DP(anc[i+1],anc[i]);
}
if (opt==1){
for (int i=1,j=x;i<=10;i++,j=fa[j])
anc[i]=j;
for (int i=10;i>1;i--)
IDP(anc[i],anc[i-1]);
for (int i=2;i<10;i++)
DP(anc[i+1],anc[i]);
fa[x]=y;
for (int i=1,j=x;i<=10;i++,j=fa[j])
anc[i]=j;
for (int i=10;i>2;i--)
IDP(anc[i],anc[i-1]);
for (int i=1;i<10;i++)
DP(anc[i+1],anc[i]);
}
if (opt==2){
for (int i=1,j=x;i<=10;i++,j=fa[j])
anc[i]=j;
for (int i=10;i>1;i--)
IDP(anc[i],anc[i-1]);
for (int i=10;i>1;i--)
DP(anc[i-1],anc[i]);
printf("%d\n",(dp[x][y]+mod)%mod);
for (int i=1;i<10;i++)
IDP(anc[i],anc[i+1]);
for (int i=1;i<10;i++)
DP(anc[i+1],anc[i]);
}
}
return 0;
}

  

2018牛客网暑假ACM多校训练赛(第二场)E tree 动态规划的更多相关文章

  1. 2018牛客网暑假ACM多校训练赛(第三场)I Expected Size of Random Convex Hull 计算几何,凸包,其他

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round3-I.html 题目传送门 - 2018牛客多校赛第三场 I ...

  2. 2018牛客网暑假ACM多校训练赛(第三场)G Coloring Tree 计数,bfs

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round3-G.html 题目传送门 - 2018牛客多校赛第三场 G ...

  3. 2018牛客网暑假ACM多校训练赛(第三场)D Encrypted String Matching 多项式 FFT

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round3-D.html 题目传送门 - 2018牛客多校赛第三场 D ...

  4. 2018牛客网暑假ACM多校训练赛(第十场)H Rikka with Ants 类欧几里德算法

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round10-H.html 题目传送门 - https://www.n ...

  5. 2018牛客网暑假ACM多校训练赛(第十场)F Rikka with Line Graph 最短路 Floyd

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round10-F.html 题目传送门 - https://www.n ...

  6. 2018牛客网暑假ACM多校训练赛(第十场)D Rikka with Prefix Sum 组合数学

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round10-D.html 题目传送门 - https://www.n ...

  7. 2018牛客网暑假ACM多校训练赛(第八场)H Playing games 博弈 FWT

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round8-H.html 题目传送门 - https://www.no ...

  8. 2018牛客网暑假ACM多校训练赛(第七场)I Tree Subset Diameter 动态规划 长链剖分 线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round7-I.html 题目传送门 -  https://www.n ...

  9. 2018牛客网暑假ACM多校训练赛(第六场)I Team Rocket 线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round6-I.html 题目传送门 - https://www.no ...

随机推荐

  1. Light OJ 1007

    求区间欧拉函数平方和... 最后因为longlong 范围爆了WA 了, 0.0 #include<bits/stdc++.h> using namespace std; const in ...

  2. CURL错误代码及含义

    https://curl.haxx.se/libcurl/c/libcurl-errors.html NAME libcurl-errors - error codes in libcurl DESC ...

  3. 解决layui选中项下一页清空问题

    项目中遇到给用户在所有产品中匹配一部分产品.用layui 第一页选好之后到第二页再选,等回到第一页时之前选择的都没了,解决这个问题的办法如下: //勾选的产品id集合 var chooseAdids ...

  4. jqgrid获取数据条数

    function getResult() {//获取结果结合的函数,可以通过此函数获取查询后匹配的所有数据行.         var o = jQuery("#jqgrid"); ...

  5. jq获取页面url后边带的参数

    //获取url后边的参数 $.getUrlParam = function (name) {                  var reg = new RegExp("(^|&) ...

  6. Confluence 6 log4j 日志级别

    日志级别 DEBUG - 被设计为用来获得最多的信息和事件,在对应用程序进行调试的时候,这个日志级别通常能够提供最多的有效信息(查看应用程序怎么了) INFO - 有关系统正常运行-计划任务运行,服务 ...

  7. Confluence 6 使用 JConsole 监控本地 Confluence

    如果你遇到了一些特定的问题,或者你仅仅是希望在一个很短的时间内监控你 Confluence 的运行,你可以使用本地监控.本地监控将会对你的服务器性能产生影响,所以我们并不推荐你使用本地监控来长时间的监 ...

  8. js之DOM对象三

      一.JS中for循环遍历测试 for循环遍历有两种 第一种:是有条件的那种,例如    for(var i = 0;i<ele.length;i++){} 第二种:for (var i in ...

  9. 1705: 小明在工作(zzuli)

    题目描述 小明的工作是负责记录饭堂中正在排队的人的信息 在他的工作中会有三种可能的事件发生:     1.编号为id的学生加入到队伍的最后面     2.排在最前面的学生打完饭离开了队伍     3. ...

  10. JMeter 提供了六种定时器

    JMeter提供了六种定时器,下面让我们一起来学习下JMeter的定时器. 先明确一些概念: 1)定时器是在每个sampler(采样器)之前执行的,而不是之后: 是的,你没有看错,不管这个定时器的位置 ...