保卫王国

保卫王国

image-20230919182149255

image-20230919182231066 image-20230919182547776

w的定义类似于上图。

并且上图是其中一类特殊情况。

image-20230919182734409

剩余状态的例图,主义这是 \(LCA:p\) 不选的情况,选的情况也是类似的。

减去 \(f_v\) 就是 在原有的 \(f_u\) 中去掉子树 \(v\) 的贡献,也可用新的 \(s\) 替换。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define Ed for(int i=h[x];~i;i=ne[i])
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=l;i>r;--i)
#define Le(i,l,r) for(int i=l;i<=r;++i)
#define Re(i,l,r) for(int i=l;i>=r;--i)
#define L(i,l) for(int i=0;i<l;++i)
#define E(i,l) for(int i=1;i<=l;++i)
#define W(t) while(t--)
#define Wh while
typedef long long ll;
const int N=100010,M=17,MM=2*N;
ll f[N][2],g[N][2],w[N][M][2][2];
int n,m,fa[N][M],p[N],dep[N];
int h[N],e[MM],ne[MM],idx;//don't forget memset h!
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs_f(int x,int fa){
    f[x][1]=p[x];
    Ed{
        int j=e[i];
        if(j==fa)continue;
        dfs_f(j,x);
        f[x][0]+=f[j][1];
        f[x][1]+=min(f[j][0],f[j][1]);
    }
}
void dfs_g(int x,int fa){
    Ed{
        int j=e[i];
        if(j==fa)continue;
        g[j][0]=f[x][1]+g[x][1]-min(f[j][0],f[j][1]);
        g[j][1]=min(g[j][0],f[x][0]+g[x][0]-f[j][1]);
        dfs_g(j,x);
    }
}
void dfs_fa(int x,int fat){
    Ed{
        int j=e[i];
        if(j==fat)continue;
        dep[j]=dep[x]+1;
        fa[j][0]=x;
        Ls(k, 1, M)fa[j][k]=fa[fa[j][k-1]][k-1];
        dfs_fa(j,x);
    }
}
void dfs_w(int x,int fat){
    Ed{
        int j=e[i];
        if(j==fat)continue;
        w[j][0][0][1]=w[j][0][1][1]=f[x][1]-min(f[j][0],f[j][1]);
        w[j][0][1][0]=f[x][0]-f[j][1];
        Ls(k, 1, M)
            L(x, 2)
                L(y, 2)
                    L(z, 2)w[j][k][x][y]=min(w[j][k][x][y],w[j][k-1][x][z]+w[fa[j][k-1]][k-1][z][y]);
        dfs_w(j,x);
    }
}
ll calc(int a,int x,int b,int y){
    if(dep[a]<dep[b])swap(a,b),swap(x,y);
    if(!x&&!y&&fa[a][0]==b)return -1;
    ll na[2],nb[2],sa[2],sb[2];
    memset(sa,0x3f,sizeof sa);
    memset(sb,0x3f,sizeof sb);
    sa[x]=f[a][x],sb[y]=f[b][y];
    Re(i, M-1, 0)
        if(dep[fa[a][i]]>=dep[b]){
            memset(na,0x3f,sizeof na);
            L(x, 2)
                L(y, 2)na[y]=min(na[y],sa[x]+w[a][i][x][y]);
            memcpy(sa,na,sizeof sa);
            a=fa[a][i];
        }
    if(a==b)return g[b][y]+sa[y];
    Re(i, M-1, 0)
        if(fa[a][i]!=fa[b][i]){
            
            memset(na,0x3f,sizeof na);
            memset(nb,0x3f,sizeof nb);
            L(x, 2)
                L(y, 2)
                na[y]=min(na[y],sa[x]+w[a][i][x][y]),
                nb[y]=min(nb[y],sb[x]+w[b][i][x][y]);
            memcpy(sa,na,sizeof sa);
            memcpy(sb,nb,sizeof sb);
            a=fa[a][i],b=fa[b][i];
        }
    int lca=fa[a][0];
    ll res0=f[lca][0]+g[lca][0]-f[a][1]-f[b][1]+sa[1]+sb[1];
    ll res1=f[lca][1]+g[lca][1]-min(f[a][1],f[a][0])-min(f[b][1],f[b][0])+min(sa[0],sa[1])+min(sb[0],sb[1]);
    return min(res0,res1);
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    #endif
    scanf("%d%d%*s",&n,&m);
    memset(h,-1,n*4+4);
    E(i, n)scanf("%d",p+i);
    E(i, n-1){
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b),add(b,a);
    }
    dfs_f(1,-1);
    dfs_g(1,-1);
    dep[1]=1;
    dfs_fa(1,-1);
    memset(w,0x3f,sizeof w);
    dfs_w(1,-1);
    W(m){
        int a,x,b,y;
        scanf("%d%d%d%d",&a,&x,&b,&y);
        printf("%lld\n",calc(a,x,b,y));
    }
    return 0;
}
posted @ 2023-09-19 18:29  wscqwq  阅读(14)  评论(0编辑  收藏  举报