动态dp入门(ddp)

大佬博客(矩阵有点问题)

大致就是写个树剖,弄个矩阵乱搞搞(满足转移)

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}
const int maxn=1e5+5;
int n,m,hd[maxn],p[maxn];
struct node{int to,nt;}e[maxn<<1];
int k;
inline void add(int x,int y){
    e[++k].to=y;e[k].nt=hd[x];hd[x]=k;
    e[++k].to=x;e[k].nt=hd[y];hd[y]=k;
}

int siz[maxn],dep[maxn],top[maxn],seg[maxn],son[maxn],fa[maxn];
inline void dfs1(int x)
{
    dep[x]=dep[fa[x]]+(siz[x]=1);
    for(int i=hd[x];i;i=e[i].nt){
        int v=e[i].to;if(v==fa[x])continue;
        fa[v]=x;dfs1(v);siz[x]+=siz[v];
        if(siz[v]>siz[son[x]])son[x]=v;
    }
}

int tot,rev[maxn],bot[maxn];
inline void dfs2(int x,int fp)
{
    top[x]=fp;seg[x]=++tot;rev[tot]=x;
    if(son[x])
    {
        dfs2(son[x],fp);
        bot[x]=bot[son[x]];
        for(int i=hd[x];i;i=e[i].nt)
            if(!top[e[i].to])dfs2(e[i].to,e[i].to);
    }
    else bot[x]=x;
}

#define ll long long
ll f[maxn][2];
inline void dp(int x)
{
    f[x][1]=p[x];f[x][0]=0;
    for(int i=hd[x];i;i=e[i].nt)
    {
        int v=e[i].to;if(v==fa[x])continue;
        dp(v);
        f[x][1]+=f[v][0];
        f[x][0]+=max(f[v][1],f[v][0]);
    }
}
//----------------------------------
struct Matrix
{
    ll s[2][2];
    inline Matrix operator*(Matrix a)const
    {
        Matrix ret;
        ret.s[0][0]=max(s[0][0]+a.s[0][0],s[0][1]+a.s[1][0]);
        ret.s[0][1]=max(s[0][0]+a.s[0][1],s[0][1]+a.s[1][1]);
        ret.s[1][0]=max(s[1][0]+a.s[0][0],s[1][1]+a.s[1][0]);
        ret.s[1][1]=max(s[1][0]+a.s[0][1],s[1][1]+a.s[1][1]);
        re ret;
    }
}t[maxn<<2],tmp[maxn];
const ll inf=2147483647;
#define ls rt<<1
#define rs rt<<1|1
inline void build(int rt,int l,int r)
{
    if(l==r)
    {
        int x=rev[l],v;
        ll g0=f[x][0]-max(f[son[x]][1],f[son[x]][0]),g1=f[x][1]-f[son[x]][0];
    /*    for(int i=hd[x];i;i=e[i].nt)
        if((v=e[i].to)!=fa[x]&&v!=son[x])
        {
            g0+=max(f[v][0],f[v][1]);
            g1+=f[v][0];
        }*/
        tmp[l]=t[rt]=(Matrix){{g0,g0,g1,-inf}};
        re ;
    }
    int mid=(l+r)>>1;
    build(ls,l,mid);build(rs,mid+1,r);
    t[rt]=t[ls]*t[rs];
}

inline void Modify(int rt,int l,int r,int pos)
{
    if(l==r)
    {
        t[rt]=tmp[l];
        re ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)Modify(ls,l,mid,pos);
    else Modify(rs,mid+1,r,pos);
    t[rt]=t[ls]*t[rs];
}

inline Matrix query(int rt,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)re t[rt];
    int mid=(l+r)>>1;
    if(y<=mid)re query(ls,l,mid,x,y);
    else if(x>mid)re query(rs,mid+1,r,x,y);
    else re query(ls,l,mid,x,y)*query(rs,mid+1,r,x,y);
}

inline Matrix Get_mat(int x){re query(1,1,n,seg[top[x]],seg[bot[x]]);}
inline void modify(int x,int y)
{
    tmp[seg[x]].s[1][0]+=(y-p[x]);p[x]=y;
    while(x)
    {
        Matrix a=Get_mat(x);Modify(1,1,n,seg[x]);
        Matrix b=Get_mat(x);
        x=fa[top[x]];
        if(!x)re;
        tmp[seg[x]].s[0][1]=(tmp[seg[x]].s[0][0]+=max(b.s[0][0],b.s[1][0])-max(a.s[0][0],a.s[1][0]));
        tmp[seg[x]].s[1][0]+=b.s[0][0]-a.s[0][0];
    }
}


int main()
{
//    freopen("in.txt","r",stdin);
    rd(n),rd(m);
    int x,y;
    inc(i,1,n)rd(p[i]);
    inc(i,2,n)
    {
        rd(x),rd(y);
        add(x,y);
    }
    
    dfs1(1);dfs2(1,1);dp(1);build(1,1,n);
    
    inc(i,1,m)
    {
        rd(x),rd(y);
        modify(x,y);
        Matrix ans=Get_mat(1);
        printf("%lld\n",max(ans.s[0][0],ans.s[1][0]));
    }
    re 0;
}

 

posted @ 2019-10-29 17:52  凉如水  阅读(543)  评论(0编辑  收藏  举报