CF2062D Banlanced Tree *2200(结论+树形dp)
\[\begin{flalign*}
&题意:给定一棵树,每个节点权值的范围是[l_i,r_i]\\&
你可以任意选择u,v使得以u为根v的子树加1&\\&
若干轮操作后,所有节点权值相等,问最小的全相等权值是多少?\\&
换根操作比较麻烦,考虑固定根节点为1,将换根操作转换成根为1的操作\\&
不换根的话就是子树加1,如果换了根的话,可以使得u子树以外的点全加1\\&
那么等价于全局加1,子树减1\\&
贪心的考虑,点权i初值设为l_i,那么每个点可以抵消r_i-l_i次全局加1操作\\&
定义f_i为使得子树全相等的最小[l_i,r_i]中的值,那么最后的答案是全局加次数+f_1
\end{flalign*}
\]
const int N=2e5+10;
int l[N],r[N];
void solve(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>l[i]>>r[i];
}
vector<vector<int>>g(n+1);
for(int i=1;i<n;i++){
int u,v; cin>>u>>v;
g[u].push_back(v),g[v].push_back(u);
}
int cnt=0;
vector<int>f(n+1,0);
auto dfs=[&](auto self,int u,int fa)->void{
f[u]=l[u];
for(auto v:g[u]){
if(v==fa) continue;
self(self,v,u);
if(f[v]>f[u]){
int temp=f[v]-f[u]-(r[u]-l[u]);
if(temp>=0){
l[u]=r[u];
}
else{
l[u]+=f[v]-f[u];
}
cnt+=max(0ll,temp);
f[u]=l[u];
}
}
};
dfs(dfs,1,0);
cout<<f[1]+cnt<<endl;
}

浙公网安备 33010602011771号