nowcoder2多校E(树型DP+可逆背包DP)

题意:给定一颗树,每个节点有权值,再给定三个操作,操作0是改变点权值,操作1是改变某点的父亲,操作2是询问包含某点的大小为k(k<=10)的联通块的价值,一个联通块的价值定义为该联通快上点权的乘积

看起来很像数据结构题,其实竟然是DP??

一个比较好的切入点是k<=10,这个带来的一个便利是,对于一个点的修改,仅涉及到他的10代祖先,那这样可以直接维护子树信息,再暴力更新维护

设d[i][j]为i为根的子树中,包含i的大小为j的联通块的价值

如果没有修改显然一遍dfs就行了。。然而带修的dp好像至今还没见过。。然后懵逼中。。

但是这个背包DP有一个很好的性质就是可撤销性,我们做这个背包做的是01背包,而撤销的方式正好是完全背包

即合并时为

dec(i,10,2)inc(j,1,i-1)d[i]+=d[i-j]*o.d[j]%inf,d[i]%=inf;

撤销为

inc(i,2,10)inc(j,1,i-1)d[i]+=inf-d[i-j]*o.d[j]%inf,d[i]%=inf;

那么对操作0,修改的时候直接去掉当前节点为根的子树,由于这个节点的背包一定包含他,即总是有他的乘积,直接除一下乘一下即可。。

对操作1,修改的时候就直接去子树和加子树

对操作2,把10代祖先去掉对应子树再合并一下就可以了

 

 

 

/**
 *        ┏┓    ┏┓
 *        ┏┛┗━━━━━━━┛┗━━━┓
 *        ┃       ┃  
 *        ┃   ━    ┃
 *        ┃ >   < ┃
 *        ┃       ┃
 *        ┃... ⌒ ...  ┃
 *        ┃       ┃
 *        ┗━┓   ┏━┛
 *          ┃   ┃ Code is far away from bug with the animal protecting          
 *          
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值