传送门

ddpddpddp模板题。

题意简述:给你一棵树,支持修改一个点,维护整棵树的最大带权独立集。


思路:

我们考虑如果没有修改怎么做。

貌似就是一个sbsbsb树形dpdpdp,fi,0f_{i,0}fi,0​表示不选iii的最大值,fi,1f_{i,1}fi,1​表示选iii的最大值。

那么可以这样从iii的儿子vvv转移过来:

fp,0+=max{fv,0,fv,1},fp,1+=fv,0f_{p,0}+=max\{f_{v,0},f_{v,1}\},f_{p,1}+=f_{v,0}fp,0​+=max{fv,0​,fv,1​},fp,1​+=fv,0​

然后就能够解决静态时候的问题。

然而现在是动态的怎么搞呢?

有句话说得好:智商不够数据结构来凑,这个时候就可以上树链剖分辣。

我们知道有点分治这种东西,同样也有链分治这种东西,也就是对于一条链维护其有关信息。

对于这道题,我们考虑维护重链的信息,考虑记一个gi,0/1g_{i,0/1}gi,0/1​表示选/不选iii点时所有轻儿子的子孙的最大独立集。

于是fi,0=gi,0+max{fhsonv,0,fhsonv,1},fi,1=gi,1+fhsonv,0f_{i,0}=g_{i,0}+max\{f_{hson_v,0},f_{hson_v,1}\},f_{i,1}=g_{i,1}+f_{hson_v,0}fi,0​=gi,0​+max{fhsonv​,0​,fhsonv​,1​},fi,1​=gi,1​+fhsonv​,0​

然后这个东西是可以用类似于矩阵乘法的东西转移的,我们将矩阵的加法重定义成取maxmaxmax,把矩阵的乘法重定义成加法。

然后就能够变成下面的矩阵转移:

(fi,0fi,1)=(gi,0gi,0gi,1−∞)∗(fv,0fv,1)
\begin{pmatrix}
f_{i,0}\\
f_{i,1}\\
\end{pmatrix}=
\begin{pmatrix}
g_{i,0}&g_{i,0}\\
g_{i,1}&-\infty\\
\end{pmatrix}*
\begin{pmatrix}
f_{v,0}\\
f_{v,1}\\
\end{pmatrix}
(fi,0​fi,1​​)=(gi,0​gi,1​​gi,0​−∞​)∗(fv,0​fv,1​​)

由于矩阵满足结合律。

所以可以上树剖,维护区间矩阵乘积。

修改的时候,从被修改节点开始沿着重链向根节点跳。对于每条重链,先对链底修改,然后更新链顶,然后跳到下一条重链继续修改即可。

每次答案就是根节点的fff值。

代码:

#include<bits/stdc++.h>
#define lc (p<<1)
#define rc (p<<1|1)
#define ri register int
#define mid (l+r>>1)
using namespace std;
const int N=1e5+5;
struct Mat{
    int g[2][2];
    Mat(){g[0][0]=g[0][1]=g[1][0]=g[1][1]=0;}
    friend inline Mat operator*(const Mat&a,const Mat&b){
        Mat ret;
        for(ri i=0;i<2;++i)for(ri k=0;k<2;++k)for(ri j=0;j<2;++j)ret.g[i][j]=max(ret.g[i][j],a.g[i][k]+b.g[k][j]);
        return ret;
    }
}T[N<<2],val[N];
int n,m,tot=0,siz[N],a[N],hson[N],top[N],bot[N],pred[N],num[N],f[N][2],fa[N];
vector<int>e[N];
void dfs1(int p){
    siz[p]=1,f[p][0]=0,f[p][1]=a[p];
    for(ri v,i=0;i<e[p].size();++i){
        v=e[p][i];
        if(v==fa[p])continue;
        fa[v]=p,dfs1(v),siz[p]+=siz[v];
        if(siz[v]>siz[hson[p]])hson[p]=v;
        f[p][0]+=max(f[v][0],f[v][1]),f[p][1]+=f[v][0];
    }
}
void dfs2(int p,int tp){
    top[p]=tp,pred[num[p]=++tot]=p;
    if(!hson[p]){bot[tp]=tot;return;}
    dfs2(hson[p],tp);
    for(ri v,i=0;i<e[p].size();++i){
        v=e[p][i];
        if(v!=fa[p]&&v!=hson[p])dfs2(v,v);
    }
}
inline void build(int p,int l,int r){
    if(l==r){
        int u=pred[l],g0=0,g1=a[u];
        for(ri v,i=0;i<e[u].size();++i){
            v=e[u][i];
            if(v!=hson[u]&&v!=fa[u])g0+=max(f[v][0],f[v][1]),g1+=f[v][0];
        }
        val[l].g[0][0]=val[l].g[0][1]=g0,val[l].g[1][0]=g1,val[l].g[1][1]=-0x3f3f3f3f,T[p]=val[l];
        return;
    }
    build(lc,l,mid),build(rc,mid+1,r),T[p]=T[lc]*T[rc];
}
inline void update(int p,int l,int r,int k){
    if(l==r){T[p]=val[l];return;}
    if(k<=mid)update(lc,l,mid,k);
    else update(rc,mid+1,r,k);
    T[p]=T[lc]*T[rc];
}
inline Mat query(int p,int l,int r,int ql,int qr){
    if(ql<=l&&r<=qr)return T[p];
    if(qr<=mid)return query(lc,l,mid,ql,qr);
    if(ql>mid)return query(rc,mid+1,r,ql,qr);
    return query(lc,l,mid,ql,mid)*query(rc,mid+1,r,mid+1,qr);
}
inline Mat ask(int p){return query(1,1,n,num[top[p]],bot[top[p]]);}
inline Mat change(int p,int x){
    val[num[p]].g[1][0]+=x-a[p],a[p]=x;
    Mat od,nw;
    while(p){
        od=ask(top[p]),update(1,1,n,num[p]),nw=ask(top[p]),p=fa[top[p]];
        val[num[p]].g[0][0]+=max(nw.g[0][0],nw.g[1][0])-max(od.g[0][0],od.g[1][0]);
        val[num[p]].g[0][1]=val[num[p]].g[0][0];
        val[num[p]].g[1][0]+=nw.g[0][0]-od.g[0][0];
    }
    return ask(1);
}
inline int read(){
    int ans=0,w=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans*w;
}
int main(){
    n=read(),m=read();
    for(ri i=1;i<=n;++i)a[i]=read();
    for(ri i=1,u,v;i<n;++i)u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
    dfs1(1),dfs2(1,1),build(1,1,n);
    while(m--){
        int x=read(),y=read();
        Mat ret=change(x,y);
        cout<<max(ret.g[0][0],ret.g[1][0])<<'\n';
    }
    return 0;
}

2019.01.04 洛谷P4719 【模板】动态dp(链分治+ddp)的更多相关文章

  1. 2019.01.04 洛谷 P4721 【模板】分治 FFT

    传送门 如同题目所描述的一样,这是一道板题. 题意简述:给你一个数组g1,2,...ng_{1,2,...n}g1,2,...n​并定义f0=1,fi=∑j=1ifi−jgjf_0=1,f_i=\su ...

  2. 【洛谷P4719】动态dp 动态dp模板

    题目大意:给你一颗$n$个点的树,点有点权,有$m$次操作,每次操作给定$x$,$y$,表示修改点$x$的权值为$y$. 你需要在每次操作之后求出这棵树的最大权独立集的权值大小. 数据范围:$n,m≤ ...

  3. 2019.01.21 洛谷P3919 【模板】可持久化数组(主席树)

    传送门 题意简述:支持在某个历史版本上修改某一个位置上的值,访问某个历史版本上的某一位置的值. 思路: 用主席树直接维护历史版本即可. 代码: #include<bits/stdc++.h> ...

  4. 2019.01.02 洛谷P4512 【模板】多项式除法

    传送门 解析 代码: #include<bits/stdc++.h> #define ri register int using namespace std; typedef long l ...

  5. 2019.01.19 洛谷P2787 语文1(chin1)- 理理思维(ODT)

    传送门 ODTODTODT水题. 题意:有一个字母序列,支持区间赋值,查询区间某个字母的数量,区间按字母序排序. 思路: 可以开262626棵线段树搞过去,然而也可以用ODTODTODT秒掉. 如果用 ...

  6. 【洛谷4719】 动态dp(树链剖分,dp,矩阵乘法)

    前言 其实我只是为了过掉模板而写的ddp,实际应用被吊着锤 Solution 并不想写详细的过程 一句话过程:将子树中轻儿子的贡献挂到这个点上面来 详细版:(引用yyb) 总结一下的话,大致的过程是这 ...

  7. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  8. 洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP

    洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他. 玩具上有一个数列,数列中某些项的值可能会 ...

  9. 洛谷P4719 【模板】"动态 DP"&动态树分治

    [模板]"动态 DP"&动态树分治 第一道动态\(DP\)的题,只会用树剖来做,全局平衡二叉树什么的就以后再学吧 所谓动态\(DP\),就是在原本的\(DP\)求解的问题上 ...

随机推荐

  1. [1.16更新B14特征处理]津南数字制造题目解读及部分思路~~有趣的特征

    [1.16更新B14特征处理]津南数字制造题目解读及部分思路--有趣的特征 Article onion啦啦啦 2019-01-17 16:03:38 11 1790 11 首先声明,我并不能保证这些特 ...

  2. [leetcode]692. Top K Frequent Words K个最常见单词

    Given a non-empty list of words, return the k most frequent elements. Your answer should be sorted b ...

  3. Linux系统不能解析域名

    问题:正在使用的Linux系统突然有一天不能解析域名gus.xxxxxxxx.com? # ping gus.xxxxxxxx.com ping: unknown host gus-xxxxxxxx. ...

  4. 线特征---LSD算法(二)

    上一节介绍了一些资源和实验结果,这节主要是介绍LSD算法理论. 直线段检测算法---LSD:a Line Segment Detector LSD的核心是像素合并于误差控制.利用合并像素来检测直线段并 ...

  5. mybatis进阶--输入映射和输出映射

    我们知道,mapper.xml是我们配置操作数据库的sql语句的地方.其中每个sql语句对应着一个方法,每个方法都有自己的输入输出参数类型.那么这些类型都是怎么配置的呢?今天我们来一起学习下. 输入映 ...

  6. PAT 1056 组合数的和(15)(代码)

    1056 组合数的和(15 分) 给定 N 个非 0 的个位数字,用其中任意 2 个数字都可以组合成 1 个 2 位的数字.要求所有可能组合出来的 2 位数字的和.例如给定 2.5.8,则可以组合出: ...

  7. php mysql 丢失更新

    php mysql 丢失更新问题,搜索整个互联网,很少有讲到,也许和php程序员出身一般都是非科班出身有关系吧. 另外php程序一般都是简单数据,很少有并发一致性问题,所以大家都没有谁专门提出这个问题 ...

  8. UI设计教程分享:关于海报的合成过程

    一张好的产品创意合成海报,能瞬间提升商品价值感,同时场景和相关元素的融入,让消费者瞬间明白商品属性及内涵.同时为商品营造的使用场景拥有更强的代入感,从而刺激转化.好的创意合成海报能为消费者带来视觉冲击 ...

  9. Laravel Session() 失效的问题

    之前因为自己自定义了后台的路由,然后路由定义的乱七八糟的. 突然发现session失效了,记录一下,避免后者遇坑. 路由组统一通过web中间件或者存在于一个中间件中 protected $middle ...

  10. lodash 中常用的方法

    odash是js集Array/Object/String/Function的Util于一身. lodash打包了Array/Object/String/Function里一些Api,好处是连ES6的也 ...