[AGE] Shik and Travel

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

1ai<i   i

0vi131072

 

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;
}

  

 

Guess you like

Origin www.cnblogs.com/linzhuohang/p/11535947.html