题目意思
S o l \mathrm{Sol} Sol
首先对于每次分别做 dp 是 O ( n 2 ) O(n^2) O(n2),即设 f u , 0 / 1 f_{u,0/1} fu,0/1 表示这个点选不选的最小代价,转移就是简单背包: f u , 0 = ∑ v ∈ u f v , 1 , f u , 1 = ∑ v ∈ u min ( f v , 0 , f v , 1 ) f_{u,0}=\sum\limits_{v∈u}f_{v,1},f_{u,1}=\sum\limits_{v∈u}\min(f_{v,0},f_{v,1}) fu,0=v∈u∑fv,1,fu,1=v∈u∑min(fv,0,fv,1)
我们考虑到每次修改只修改 u ∼ v u\sim v u∼v 两点到其 l c a lca lca 上的链以及 l c a lca lca 到根的链的贡献所以我们考虑每次修改贡献的加减。
于是我们考虑倍增,设 g 0 / 1 , 0 / 1 , u , i g_{0/1,0/1,u,i} g0/1,0/1,u,i 表示 u u u 是否选, u u u 的 2 i 2^i 2i 祖先选不选的 dp 值,这个预处理还是不难的,即我们每次考虑 u u u 的 2 i − 1 2^{i-1} 2i−1 祖先的是否取状态来合并即可,具体实现可以看代码。
然后我们来考虑如何转移答案:假设 u u u 新的 dp 值为 h x h_x hx 那么对于更新 f a u fa_u fau 的 dp 值,莫过于选或不选两种情况: f f a u , 0 − f u , 1 + h x f_{fa_u,0}-f_{u,1}+h_x ffau,0−fu,1+hx 或 f f a u , 1 − min ( f u , 0 , f u , 1 ) + h x f_{fa_u,1}-\min(f_{u,0},f_{u,1})+h_x ffau,1−min(fu,0,fu,1)+hx。
时间复杂度 O ( n log n ) O(n\log n) O(nlogn)
C o d e \mathrm{Code} Code
const int mod=1e9+7;
const int mo=998244353;
const int N=5e5+5;
int n,m,dp[N][2],g[2][2][21][N];
int dep[N],f[N][22],a[N];
vector<int> G[N];
char s[5];
inline void dfs(int u,int fa)
{
dep[u]=dep[fa]+1;
f[u][0]=fa;
For(i,1,19) f[u][i]=f[f[u][i-1]][i-1];
dp[u][1]=a[u];
g[0][0][0][u]=1e15;
For(i,0,(int)G[u].size()-1)
{
int v=G[u][i];
if(v==fa) continue;
dfs(v,u);
dp[u][0]+=dp[v][1];
dp[u][1]+=min(dp[v][1],dp[v][0]);
}
}
inline void Dfs(int u)
{
g[1][0][0][u]=dp[f[u][0]][0]-dp[u][1];
g[1][1][0][u]=g[0][1][0][u]=dp[f[u][0]][1]-min(dp[u][0],dp[u][1]);
For(i,1,19)
{
int fa=f[u][i-1];
g[0][0][i][u]=min(g[0][0][i-1][u]+g[0][0][i-1][fa],g[0][1][i-1][u]+g[1][0][i-1][fa]);
g[0][1][i][u]=min(g[0][1][i-1][u]+g[1][1][i-1][fa],g[0][0][i-1][u]+g[0][1][i-1][fa]);
g[1][0][i][u]=min(g[1][0][i-1][u]+g[0][0][i-1][fa],g[1][1][i-1][u]+g[1][0][i-1][fa]);
g[1][1][i][u]=min(g[1][0][i-1][u]+g[0][1][i-1][fa],g[1][1][i-1][u]+g[1][1][i-1][fa]);
}
For(i,0,(int)G[u].size()-1)
{
int v=G[u][i];
if(v==f[u][0]) continue;
Dfs(v);
}
}
signed main()
{
io.read(n),io.read(m);
scanf("%s",s+1);
For(i,1,n) io.read(a[i]);
For(i,1,n-1)
{
int x,y;
io.read(x),io.read(y);
G[x].pb(y),G[y].pb(x);
}
dfs(1,0);
Dfs(1);
for (;m--;)
{
int a,x,b,y,L;
io.read(a),io.read(x),io.read(b),io.read(y);
if(dep[a]<dep[b]) swap(x,y),swap(a,b);
int u0=1e15,u1=1e15,v0=1e15,v1=1e15,l1=1e15,l0=1e15,ans;
(x)?u1=dp[a][1]:u0=dp[a][0];
(y)?v1=dp[b][1]:v0=dp[b][0];
Dow(i,19,0) if(dep[a]-(1ll<<i)>=dep[b])
{
int t0=u0,t1=u1;
u0=min(t0+g[0][0][i][a],t1+g[1][0][i][a]);
u1=min(t0+g[0][1][i][a],t1+g[1][1][i][a]);
a=f[a][i];
}
if(a==b) L=a,(y)?l1=u1:l0=u0;
else
{
Dow(i,19,0) if(f[a][i]^f[b][i])
{
int t0=u0,t1=u1;
int s0=v0,s1=v1;
u0=min(t0+g[0][0][i][a],t1+g[1][0][i][a]);
u1=min(t0+g[0][1][i][a],t1+g[1][1][i][a]);
v0=min(s0+g[0][0][i][b],s1+g[1][0][i][b]);
v1=min(s0+g[0][1][i][b],s1+g[1][1][i][b]);
a=f[a][i],b=f[b][i];
}
L=f[a][0];
l0=dp[L][0]-dp[a][1]-dp[b][1]+u1+v1;
l1=dp[L][1]-min(dp[a][0],dp[a][1])-min(dp[b][0],dp[b][1])+min(u1,u0)+min(v1,v0);
}
if(L==1) ans=min(l0,l1);
else
{
Dow(i,19,0) if(dep[L]-(1ll<<i)>1)
{
int t0=l0,t1=l1;
l0=min(t0+g[0][0][i][L],t1+g[1][0][i][L]);
l1=min(t0+g[0][1][i][L],t1+g[1][1][i][L]);
L=f[L][i];
}
ans=min(dp[1][0]-dp[L][1]+l1,dp[1][1]-min(dp[L][0],dp[L][1])+min(l0,l1));
}
if(ans==1e15) ans=-1;
io.write(ans);
puts("");
}
return 0;
}