Luogu5024 保卫王国

https://www.luogu.com.cn/problem/P5024

动态DP

\(f_{u,0}\)表示以\(u\)为根的子树中,\(u\)不取的最小开销

\(f_{u,1}\)表示以\(u\)为根的子树中,\(u\)必取的最小开销

\(g_{u,0}\)表示以\(u\)为根的子树中,不取重儿子,且\(u\)不取的最小开销

\(g_{u,1}\)表示以\(u\)为根的子树中,不取重儿子,且\(u\)必取的最小开销

\(u\)的重儿子为\(w\)

\[f_{u,0}=g_{u,0}+f_{w,1}\\ f_{u,1}=g_{u,1}+\min(f_{w,0},f_{w,1}) \]

转化方程

\[f_{u,0}=\min(+\infty+f_{w,0},g_{u,0}+f_{w,1})\\ f_{u,1}=\min(g_{u,1}+f_{w,0},g_{u,1}+f_{w,1}) \]

重定义矩阵乘法运算

\[C_{i,j}=\min A_{i,k}+B_{k,j} \]

转化为矩阵乘法

\[\begin{vmatrix} +\infty & g_{u,0}\\ g_{u,1} & g_{u,1} \end{vmatrix} \times \begin{vmatrix} f_{w,0} \\ f_{w,1} \end{vmatrix} = \begin{vmatrix} f_{u,0} \\ f_{u,1} \end{vmatrix} \]

初始化叶子节点

\[\begin{vmatrix} 0 \\ Val_i \end{vmatrix} \]

转化成\(2\times 2\)矩阵

\[\begin{vmatrix} 0 & +\infty \\ Val_i & +\infty \end{vmatrix} \]

基本结束

注意:节点\(a,b\)\(g\)值也需要修改后再修改全局平衡二叉树

\(Code:\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 100005
#define INF 10000000000007
#define ll long long
#define fa(x) F[x]
#define ls(x) ch[x][0]
#define rs(x) ch[x][1]
using namespace std;
int n,m,a,b,x,y,tot,rt,frt,val[N],fr[N],nxt[N << 1],d[N << 1];
int F[N],sz[N],son[N];
int q[N],qz[N];
int ch[N][2];
ll rc,rd,f[N][2],g[N][2];
char ty[5];
struct mat
{
    ll w[2][2];
    void setmat(ll a=0,ll b=INF,ll c=INF,ll d=0)
    {
        w[0][0]=a,w[0][1]=b;
        w[1][0]=c,w[1][1]=d;
    }
    mat operator * (mat b)
    {
        mat c;
        c.w[0][0]=min(w[0][0]+b.w[0][0],w[0][1]+b.w[1][0]);
        c.w[0][1]=min(w[0][0]+b.w[0][1],w[0][1]+b.w[1][1]);
        c.w[1][0]=min(w[1][0]+b.w[0][0],w[1][1]+b.w[1][0]);
        c.w[1][1]=min(w[1][0]+b.w[0][1],w[1][1]+b.w[1][1]);
        return c;
    }
    ll mn()
    {
        return min(w[0][0],w[1][0]);
    }
}z[N],s[N],ra,rb;
void add(int x,int y)
{
    tot++;
    d[tot]=y;
    nxt[tot]=fr[x];
    fr[x]=tot;
}
void dfs1(int u)
{
    int mx=-1;
    sz[u]=1;
    for (int i=fr[u];i;i=nxt[i])
    {
        int v=d[i];
        if (v==F[u])
            continue;
        F[v]=u;
        dfs1(v);
        sz[u]+=sz[v];
        if (sz[v]>mx)
        {
            mx=sz[v];
            son[u]=v;
        }
    }
}
void update(int x)
{
    s[x]=s[ls(x)]*z[x]*s[rs(x)];
}
int build(int l,int r)
{
    if (l>r)
        return 0;
    int hs=(qz[r]-qz[l-1]) >> 1,o;
    int L=l,R=r;
    while (L<=R)
    {
        int mid=(L+R) >> 1;
        if (qz[mid]-qz[l-1]>=hs)
        {
            o=mid;
            R=mid-1;
        } else
            L=mid+1;
    }
    ls(q[o])=build(l,o-1);
    rs(q[o])=build(o+1,r);
    update(q[o]);
    fa(ls(q[o]))=q[o];
    fa(rs(q[o]))=q[o];
    return q[o];
}
void dfs2(int u)
{
    g[u][0]=0,g[u][1]=val[u];
    if (!son[u])
    {
        f[u][0]=g[u][0],f[u][1]=g[u][1];
        z[u].setmat(0,INF,val[u],INF);
    } else
    {
        dfs2(son[u]);
        for (int i=fr[u];i;i=nxt[i])
        {
            int v=d[i];
            if (v==F[u] || v==son[u])
                continue;
            dfs2(v);
            g[u][0]+=f[v][1];
            g[u][1]+=min(f[v][0],f[v][1]);
        }
        f[u][0]=g[u][0]+f[son[u]][1];
        f[u][1]=g[u][1]+min(f[son[u]][0],f[son[u]][1]);
        z[u].setmat(INF,g[u][0],g[u][1],g[u][1]);
    }
    if (son[F[u]]!=u)
    {
        frt=F[u];
        q[0]=0;
        for (int v=u;v;v=son[v])
            q[++q[0]]=v,qz[q[0]]=qz[q[0]-1]+sz[v]-sz[son[v]];
        rt=build(1,q[0]);
        F[rt]=frt;
    }
}
bool isrt(int x)
{
    return ls(fa(x))!=x && rs(fa(x))!=x;
}
void modify(int x)
{
    for (int u=x;u;u=F[u])
        if (!isrt(u) || !fa(u))
            update(u); else
            {
                int v=fa(u);
                g[v][0]-=s[u].w[1][0];
                g[v][1]-=min(s[u].w[0][0],s[u].w[1][0]);
                update(u);
                g[v][0]+=s[u].w[1][0];
                g[v][1]+=min(s[u].w[0][0],s[u].w[1][0]);
                z[v].setmat(INF,g[v][0],g[v][1],g[v][1]);
            }
}
int main()
{
    scanf("%d%d%s",&n,&m,ty);
    for (int i=1;i<=n;i++)
        scanf("%d",&val[i]);
    for (int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y),add(y,x);
    }
    dfs1(1);
    z[0].setmat(),s[0].setmat();
    dfs2(1);
    while (m --> 0)
    {
        scanf("%d%d%d%d",&a,&x,&b,&y);
        ra=z[a];
        if (x==0)
            rc=g[a][1],g[a][1]=INF; else
            rc=g[a][0],g[a][0]=INF;
        if (son[a])
        {
            if (x==0)
                z[a].w[1][0]=z[a].w[1][1]=INF; else
                z[a].w[0][1]=INF;
        } else
        {
            if (x==0)
                z[a].w[1][0]=INF; else
                z[a].w[0][0]=INF;
        }
        modify(a);
        rb=z[b];
        if (y==0)
            rd=g[b][1],g[b][1]=INF; else
            rd=g[b][0],g[b][0]=INF;
        if (son[b])
        {
            if (y==0)
                z[b].w[1][0]=z[b].w[1][1]=INF; else
                z[b].w[0][1]=INF;
        } else
        {
            if (y==0)
                z[b].w[1][0]=INF; else
                z[b].w[0][0]=INF; 
        }
        modify(b);
        printf("%lld\n",(s[rt].mn()<INF)?s[rt].mn():-1);
        if (y==0)
            g[b][1]=rd; else
            g[b][0]=rd;
        z[b]=rb;
        modify(b);
        if (x==0)
            g[a][1]=rc; else
            g[a][0]=rc;
        z[a]=ra;
        modify(a);
    }
    return 0;
}
posted @ 2020-09-18 20:18  GK0328  阅读(135)  评论(0编辑  收藏  举报