Official Editorial (Chinese)

Explanation

Naive Solution

We observe that any operation will only affect nodes of the same depth. Thus, instead of solving for all depths at once, we can take the sum of the minimum cost to fill in each depth.

Consider the set of nodes at depth dd relative to the root. Define dp[v]\texttt{dp}[v] as the minimum cost to fill in all vertices of depth dd in the subtree of vv, only considering operations selecting vertices at vv or lower.

  • If vv is of depth dd (relative to the root), then we must fill it in with cost a0a_0
dp[v]=a0\texttt{dp}[v] =a_0
  • Otherwise, we can either select to incur a cost of addepth[v]a_{d-\text{depth}[v]} by operating on vv, or not operate on vv and instead solve for each subtree:
dp[v]=min(addepth[v],uChildren(v)dp[u])\texttt{dp}[v] = \min\left( a_{d-\text{depth}[v]},\sum_{u\in\text{Children}(v)} \text{dp}[u]\right)

Our answer will be the sum of dp[0]\texttt{dp}[0] for each value of dd, yielding a solution in O(n2)\mathcal{O}(n^2) time.

Virtual Tree Optimization

One observation we can make is for a long chain ending at vv, we can process it quickly by taking

dp[v]=min(minx[ddepth[v],d]ax,uChildren(v)dp[u])\texttt{dp}[v] = \min \left( \min_{x\in[d-\text{depth}[v],d]}a_x, \sum_{u\in\text{Children}(v)} \text{dp}[u] \right)

We will aim to leverage this fact. Define SdS_d as the set of vertices at depth dd, and take SS to be the virtual tree of SdS_d.

We continue in a similar fashion to previously, but we only compute dynamic programming values for nodes in SS. The range minimum query can be answered using data structures in logarithmic or linear time.

dp[v]=min(minx[ddepth[v],d]ax,uVirtual Children(v)dp[u])\texttt{dp}[v] = \min \left( \min_{x\in[d-\text{depth}[v],d]}a_x, \sum_{u\in\text{Virtual Children}(v)} \text{dp}[u] \right)

Implementation

Time Complexity: O(NlogN)\mathcal{O}(N \log N)

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr int MAX_N = 1e5 + 1;
constexpr int LG = 17;
int tin[MAX_N], tout[MAX_N], d[MAX_N], lift[MAX_N][LG], timer;
ll dp[MAX_N];

Join the USACO Forum!

Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!