zoukankan      html  css  js  c++  java
  • 「LGP4719【模板】动态dp」

    题目

    尽管知道这个东西应该不会考了,但是还是学一学吧

    哎要是去年noip之前学该多好

    动态(dp)就是允许修改的一个(dp),比如这道题,我们都知道这是一个树上最大点权独立集

    众所周知方程长这个样子

    [dp_{u,0}=sum_{(u,v)in e}min(dp_{v,0},dp_{v.1}) ]

    [dp_{u,1}=a_v+sum_{(u,v)in e}dp_{v,0} ]

    但是有了修改我们就没有办法做了

    写不下去了,挂一个yyb跑路吧

    大概就是一句话,维护处每一个点的轻儿子的转移矩阵,由于一个链的链底没有儿子,于是整个重链乘起来就是答案

    放上板子

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define LL long long
    #define inf 999999999999
    #define re register
    #define maxn 100005
    inline int read() {
        char c=getchar();int x=0,r=1;
        while(c<'0'||c>'9') {if(c=='-') r=-1;c=getchar();}
        while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x*r;
    }
    inline LL max(LL a,LL b) {return a>b?a:b;}
    struct mat{LL a[2][2];}d[maxn<<2];
    mat operator*(mat a,mat b) {
        mat c;
        c.a[0][0]=max(a.a[0][0]+b.a[0][0],a.a[0][1]+b.a[1][0]);
        c.a[0][1]=max(a.a[0][1]+b.a[1][1],a.a[0][0]+b.a[0][1]);
        c.a[1][0]=max(a.a[1][0]+b.a[0][0],a.a[1][1]+b.a[1][0]);
        c.a[1][1]=max(a.a[1][1]+b.a[1][1],a.a[1][0]+b.a[0][1]);
        return c;
    }
    struct E{int v,nxt;}e[maxn<<1];
    int sum[maxn],dfn[maxn],top[maxn],son[maxn],deep[maxn],fa[maxn],mx[maxn];
    LL dp[maxn][2];int head[maxn],a[maxn],pos[maxn],to[maxn];
    int n,m,num,__;
    int l[maxn<<2],r[maxn<<2];
    inline void C(int x,int y) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;}
    void dfs1(int x) {
        sum[x]=1;int maxx=-1;
        for(re int i=head[x];i;i=e[i].nxt) {
            if(deep[e[i].v]) continue;
            deep[e[i].v]=deep[x]+1,fa[e[i].v]=x;
            dfs1(e[i].v);sum[x]+=sum[e[i].v];
            if(sum[e[i].v]>maxx) son[x]=e[i].v,maxx=sum[e[i].v];
        }
    }
    void dfs2(int x,int topf) {
        top[x]=topf,dfn[x]=++__,to[__]=x;
        if(!son[x]) return;
        dfs2(son[x],topf);
        for(re int i=head[x];i;i=e[i].nxt) {
            if(top[e[i].v]) continue;
            dfs2(e[i].v,e[i].v);
        }
    }
    inline void pushup(int i) {d[i]=d[i<<1]*d[i<<1|1];}
    void add(int i,int val) {d[i].a[1][0]+=val;while(i) {i>>=1;pushup(i);}}
    void change(int i,mat val) {d[i]=val;while(i) {i>>=1;pushup(i);}}
    void build(int x,int y,int i) {
        l[i]=x,r[i]=y;
        if(x==y) {
            int now=to[x];dp[now][1]+=a[now];
            for(re int j=head[now];j;j=e[j].nxt) {
                if(deep[e[j].v]<deep[now]) continue;
                if(e[j].v==son[now]) continue;
                dp[now][0]+=max(dp[e[j].v][1],dp[e[j].v][0]);
                dp[now][1]+=dp[e[j].v][0];
            }
            d[i].a[0][0]=dp[now][0],d[i].a[0][1]=dp[now][0];
            d[i].a[1][0]=dp[now][1],d[i].a[1][1]=-inf;
            if(son[now]) 
                dp[now][0]+=max(dp[son[now]][1],dp[son[now]][0]),dp[now][1]+=dp[son[now]][0];
            pos[now]=i;
            return;
        }
        int mid=x+y>>1;
        build(mid+1,y,i<<1|1),build(x,mid,i<<1);
        pushup(i);
    }
    mat query(int x,int y,int i) {
        if(x<=l[i]&&y>=r[i]) return d[i];
        int mid=l[i]+r[i]>>1;
        if(y<=mid) return query(x,y,i<<1);
        if(x>mid) return query(x,y,i<<1|1);
        return query(x,y,i<<1)*query(x,y,i<<1|1);
    }
    int main() {
        n=read(),m=read();
        for(re int i=1;i<=n;i++) a[i]=read();
        for(re int x,y,i=1;i<n;i++) {
            x=read(),y=read();C(x,y),C(y,x);
        }
        deep[1]=1,dfs1(1),dfs2(1,1),build(1,n,1);
        for(re int i=1;i<=n;i++) 
            if(deep[i]>deep[mx[top[i]]]) mx[top[i]]=i;
        for(re int x,y,i=1;i<=m;i++){
            x=read(),y=read();
            mat pre=query(dfn[top[x]],dfn[mx[top[x]]],1);
            add(pos[x],-a[x]+y);a[x]=y;
            while(x) {
                if(top[x]==1) break;
                mat now=query(dfn[top[x]],dfn[mx[top[x]]],1);
                mat t=d[pos[fa[top[x]]]];
                t.a[0][0]-=max(pre.a[0][0],pre.a[1][0]),t.a[0][1]=t.a[0][0];
                t.a[1][0]-=pre.a[0][0];
                t.a[0][0]+=max(now.a[0][0],now.a[1][0]),t.a[0][1]=t.a[0][0];
                t.a[1][0]+=now.a[0][0];
                x=fa[top[x]];
                pre=query(dfn[top[x]],dfn[mx[top[x]]],1);
                change(pos[x],t);
            }
            mat s=query(1,dfn[mx[1]],1);
            printf("%lld
    ",max(s.a[0][0],s.a[1][0]));
        }
        return 0;
    }
    
  • 相关阅读:
    使用dom4j 解析xml
    xml schema 建立xml文档
    xml dtd 约束建立xml文档
    DBCP 连接池的使用
    c++面向过程和面向对象-C++编译器是如何管理类和对象的
    c++读取文本文件
    一个范围的两个数进行数位的累加,实现对两个数num1和num2的数位和相加
    C++批量注释代码段取消注释代码段快捷键
    利用MATLAB截取一张复杂图片中想要的区域
    python学习之路系列
  • 原文地址:https://www.cnblogs.com/asuldb/p/10543860.html
Copyright © 2011-2022 走看看