[bzoj2286][Sdoi2011]消耗战
题目链接 如果对于每个询问跑一次$dp$,那么$dp[i]$为断开$i$这棵子树的最小花费。 这样的复杂度为$O(n*m)$,过于臃肿。 所以我们要对于每次询问降低这次询问的复杂度。 我们可以发现$m$个关键点,最多有$m-1$个$lca$。 简单证明一下,如果有两个点,会有$1$个$lca$点,如果有三个点,则第三个点会和上一个$lca$产生一个$lca$。 所以以这$2*m-1$个点构建一棵树,在这个树上跑$dp$ 虚树的构建推荐一个 巨巨的博客 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 250010; 5 const ll inf = 2e18 + 10; 6 struct node { 7 int s, e, next; 8 ll w; 9 }edge[maxn * 2]; 10 int head[maxn], len; 11 void init() { 12 memset(head, -1, sizeof(head)); 13 len = 0; 14 } 15 void add(int s, int e, ll w) { 16 edge[len] = { s,e,head[s],w }; 17 head[s] = len++;