topic
A given node n to a full binary tree root (each non-leaf node has exactly two sons)
n-1 edges Article ii edges connecting point and the number i + 1 ai, after consideration of vi
provided this tree has m leaf nodes
define a legitimate travel to:
(1) m + 1 day trip, travel starting from No. 11, and finally back to No. 11
(2) 1 ..m the first day, from the day the end point of the day of departure, went to a leaf node, then the end of the day
(the end point in mind at day 0 to 1)
the first m + 1 days, starting from the end point of the day, went to No. 1 point
(3) during travel , each side just after the two
defined spending the day as follows: beginning to the end of the right side and
the definition of the cost of a trip is: the first 2 ..m days, it takes a maximum value ** **
find an optimal travel scheme, such that the minimum cost of travel ** **
minimum output
2<n<131072
1≤ai<i ∀i
0≤vi≤131072
answer
Observed $ vi <= 131072 $, we can answer half of ANS (selecting the maximum value of this minimum, the minimum value of the maximum binary usually is)
For each node maintains a stack $ I $ $ (a, b) $ indicates the presence of a start of the current sub-tree, the end of the I $ $ $ a distance respectively, and the longest path B does not exceed $ $ $ ANS complete traversal subtrees program
Now talk about how merge
Because this is a full binary tree, so the current point i plan must be left to the son of the right son went to $ lc $ $ rc $, or vice versa.
Son assume the starting point on the left, then the program is $ (a, b) = (lc.a + cost_left, rc.b + cost_right).
But this process also $ lc.end -> i -> rc.start $ this path
So also meet the $ lc.b + cost_left + cost_right + rc.a <= ans $
However, we can not for every $ (lc.a, lc.b) $ scans all $ (rc.a, rc.b) $
Therefore, for the same a, we retain only the smallest b, b is the same reason.
In addition to $ (a, b) $, if can find $ (c, d) $ such that $ c <= a, d <= b $ then (a, b) will not retain the necessary
So, when we go back to each node (a, b) for a small to large order
Because a increment, decrement so b (otherwise there would be no need to retain)
Therefore, we can use the double pointer to accelerate combined (see the specific code) at the time of merging.
As a starting point in a merger case lc with the starting point in the rc, you can use merge sort of thought
Code
#include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <map> using namespace std; #define N 140000 #define int long long #define pr pair<int,int> vector<pr> vec[N],_left,_right; int mid; vector<pr> dfs(int id,int from) { //cout<<id<<" "<<from<<endl; vector<pr> lc,rc,now; int cl=-1,cr; if(vec[id].size()==1&&from) { now.push_back(make_pair(0,0)); return now; } for(int i=0;i<vec[id].size();i++) { pr l=vec[id][i]; if(l.first==from) continue; vector <pr> t = dfs ( l.first, id); // return (a, b) incrementing the a, b and thus decreasing IF (Cl <0) = T LC, Cl = l.second; the else RC = T, Cr = l.second; } int J = 0; for (int I = 0; I <lc.size (); I ++) // choose the starting point in the left subtree, satisfying the condition, the optimal (a, b), the new (a, B) = (LC [I] .first, RC [I] .second) { the while (J +. 1 <rc.size () && LC [I] .second RC + [J + 1] .first + cl + cr < = mid) j ++; // find rc satisfy the condition b minimum (a, b). Because only takes a minimum is the same B IF (rc.size () && LC [I] .second RC + [J] .first + Cl + Cr <= MID) _left.push_back (the make_pair (LC [I] .first + cl, rc [j] .second + cr)); // the foregoing (a, b) to surely current difference, so do not find RC [. 1. 1-J ~] } J = 0; for (int I = 0; i <rc.size () ; i ++) // right subtree select a start, to meet the conditions, the optimal (a, b), the new (a, b) = (rc [i] .first , lc [i] .second) { the while (J +. 1 <lc.size () && RC [I] .second LC + [J +. 1] .first + Cl + Cr <= MID) J ++; IF (lc.size () && RC [I] .second LC + [J] .first + Cl + Cr <= MID) _right.push_back (the make_pair (RC [I] .first + Cr, LC [J] .second + Cl)); } // at this time and _left _right must be ordered, a synthesis of a now increasing, decreasing array int L = 0, R & lt = 0, = Last 0x7FFFFFFFFFFFFFFF; the while (L <_left.size () R & lt || <_right.size ()) // merge sort similar ideas { IF (L <_left.size () && (R & lt> = _ right.size () || _Left [L] <= _ right [R & lt])) { IF (_Left [L] .second <last) // now there is optimal in order to ensure, b is decremented by { Last _Left = [L] .second; now.push_back (_Left [L]); } L ++; } else { if(_right[r].second<last) { last=_right[r].second; now.push_back(_right[r]); } r++; } } _left.clear(),_right.clear(); return now; } signed main() { int n; cin>>n; for(int i=2;i<=n;i++) { int a,v; scanf("%lld%lld",&a,&v); vec[a].push_back(make_pair(i,v)); vec[i].push_back(make_pair(a,v)); } int l=0,r=17179869184; while(r-l>1) { mid=(l+r)/2; //cout<<l<<" "<<mid<<" "<<r<<endl; if(!dfs(1,0).empty()) r=mid; else l=mid; } mid=l; if(!dfs(1,0).empty()) cout<<l; else cout<<r; }