题目分析:
不难发现可以用动态DP做。
题目相当于是要我求一条路径,所有与路径有交的链的代价加入进去,要求代价最大。
我们把链的代价分成两个部分:一部分将代价加入$LCA$之中,用$g$数组保存;另一部分将代价加在整条链上,用$d$数组保存。
这时候我们可以发现,一条从$u$到$v$的路径的代价相当于是$d[LCA(u,v)]+\sum_{x \in edge(u,v)}g[x]$。
如果是静态的,可以用树形DP解决。
看过《神奇的子图》的同学都知道,叶子结点是从它的儿子中取两个最大的出来,所以堆维护。
考虑合并。
链从左延申出的最大的$g$的总和记录。链从右延申包括$d$的总和记录,每次向上$update$的时候拼起来与原答案比较即可。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 6 const int maxn = 102000; 7 8 int n,m; 9 10 vector <int> g[maxn]; 11 int sz[maxn],top[maxn],fa[maxn],dep[maxn],son[maxn],ind[maxn],dr[maxn]; 12 int tail[maxn],num; 13 14 struct Query{int from,to,w;}Q[maxn]; 15 struct Priority_Queue{ 16 priority_queue<ll,vector<ll>,less<ll> > pq,del; 17 void push(ll now){pq.push(now);} 18 void pop(){ 19 while(!del.empty() && pq.top() == del.top()) pq.pop(),del.pop(); 20 pq.pop(); 21 } 22 ll top(){ 23 while(!del.empty() && pq.top() == del.top()) pq.pop(),del.pop(); 24 if(pq.empty()) return 0; 25 else return pq.top(); 26 } 27 ll sec(){ 28 while(!del.empty() && pq.top() == del.top()) pq.pop(),del.pop(); 29 if(pq.size() ==0) return 0; 30 ll oop = pq.top(); pq.pop(); 31 while(!del.empty() && pq.top() == del.top()) pq.pop(),del.pop(); 32 if(pq.size() == 0){pq.push(oop);return 0;}