Topic Link
https://atcoder.jp/contests/agc007/tasks/agc007_e
answer
First, there is a very simple idea is half the answer \ (mid \) using a feasibility DP, set \ (dp [u] [x ] [y] \) represents \ (u \) if you can find a sub-tree of a path, after the first leaves from the front is \ (the X-\) , after the last one before the leaves away is \ (the y-\) .
the DP obviously done a lot of useful work, such as we find totally true status can be recorded only \ ( (X, Y) \) , is further found that if a legal state \ ((x, y) \ ) there is another legal status \ ((x ', y' ) \) satisfies \ (x '\ le x, y' < \ the y-Le \) , then there is no need to store \ ((x, y) \ ) a. So we press \ (x \) in order of increasing storage \ ((the X-, the y-) \) , so \ (y \) must be decreasing.
After this simplification, we found a magical nature: Let \ (S_u \) to \ (u \) a collection of records, \ (i \) and \ (j \) for his son, then \ (| S_u | \ le 2 \ min (| S_i |, | S_j |) \)This is because \ (x \) and \ (y \) values have their own \ (\ min (| S_i | , | S_j |) \) species.
Consider the process of merging: the beginning of the assumptions paths \ (i \) inside, then we need to find \ ((x_1, Y_1) \ in S_i, (x_2, y_2) \ in S_j \) , if \ (y_1 + v_i + + x_2 v_J \ Le MID \) , put \ ((x_1 + v_i, y_2 + w_j) \) was added \ (S_u \) . this will be apparent by the double pointer optimization. this path starts at \ \) (J is also on empathy.
Heuristic analysis can merge similar complexity. Half of the total count complexity \ (O (n-\ log ^ 2N) \) .
Code
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cassert>
#include<vector>
#define llong long long
#define pll pair<llong,llong>
#define mkpr make_pair
using namespace std;
const int N = 1<<17;
int son[N+3][2];
llong w[N+3];
vector<pll> dp[N+3];
vector<pll> aux1,aux2;
int n,en;
llong mid;
void dfs(int u)
{
// printf("dfs %d\n",u);
dp[u].clear(); int ls = son[u][0],rs = son[u][1];
if(!ls)
{
dp[u].push_back(mkpr(0ll,0ll));
return;
}
dfs(ls); dfs(rs);
aux1.clear(); aux2.clear();
if(dp[rs].size())
{
int j = 0;
for(int i=0; i<dp[ls].size(); i++)
{
while(j<dp[rs].size()-1 && dp[rs][j+1].first+dp[ls][i].second+w[ls]+w[rs]<=mid) {j++;}
if(j<dp[rs].size() && dp[rs][j].first+dp[ls][i].second+w[ls]+w[rs]<=mid) {aux1.push_back(mkpr(dp[ls][i].first+w[ls],dp[rs][j].second+w[rs]));}
}
}
if(dp[ls].size())
{
int j = 0;
for(int i=0; i<dp[rs].size(); i++)
{
while(j<dp[ls].size()-1 && dp[ls][j+1].first+dp[rs][i].second+w[ls]+w[rs]<=mid) {j++;}
if(j<dp[ls].size() && dp[ls][j].first+dp[rs][i].second+w[ls]+w[rs]<=mid) {aux2.push_back(mkpr(dp[rs][i].first+w[rs],dp[ls][j].second+w[ls]));}
}
}
int j = 0,k = 0; llong cur = 1ll<<34;
while(j<aux1.size() || k<aux2.size())
{
if(k==aux2.size() || (j<aux1.size() && aux1[j].first<=aux2[k].first))
{
if(aux1[j].second<cur) {dp[u].push_back(aux1[j]); cur = aux1[j].second;}
j++;
}
else
{
if(aux2[k].second<cur) {dp[u].push_back(aux2[k]); cur = aux2[k].second;}
k++;
}
}
}
bool check()
{
dfs(1);
if(dp[1].size()) {return true;}
else {return false;}
}
int main()
{
scanf("%d",&n);
for(int i=2; i<=n; i++)
{
int u; llong x; scanf("%d%lld",&u,&x);
w[i] = x; if(son[u][0]) son[u][1] = i; else son[u][0] = i;
}
llong left = 0ll,right = 1ll<<34;
while(left<right)
{
mid = left+((right-left)>>1)
// printf("mid=%lld\n",mid);
bool ok = check();
if(ok) {right = mid;}
else {left = mid+1;}
}
printf("%lld\n",right);
return 0;
}