#include "roads.h"
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define st first
#define nd second
#define pb push_back
const int NN = 1e5+3;
const ll INF = 1e15;
vector<int> inp[NN], Vdeg[NN], grf[NN];
int pre[NN], cnt, par[NN], idx[NN];
bool odw[NN];
ll Dp[NN][2], C[NN];
// dla solva WTH OMG OMG 
// CHINESE FISHERMAN NEVER GIVE UP!!!
vector<pair<ll, ll>> trees[NN];
int base[NN];
// dla n^2 log
vector<ll> tmpX, tmpY;
bool comp(int a, int b){
    return (int)inp[a].size() > (int)inp[b].size();
}
void set_pre(int v, int p){
    pre[v]=cnt; cnt++; par[v]=p;
    for(auto w:inp[v]){
        if(w==p) continue;
        set_pre(w, v);
    }
}
ll get_y(int v, int k){
    ll out = 0;
    tmpY.pb(-INF);
    for(auto w:inp[v]) if((int)inp[w].size()>k && pre[v]<pre[w]) out+=Dp[w][0], tmpY.pb(Dp[w][1]-Dp[w][0]);
    sort(tmpY.begin(), tmpY.end());
    tmpY[0]=0;
    return out;
}
ll get_sm_x(int v, int x){
    int cur=1;
    ll out=0;
    while(2*cur<2*base[v]){
        //cout << "V: " << v << ' ' << "X: " << x << " CUR: " << cur << ' ' << trees[v][cur].nd << '\n';
        if(trees[v][cur].nd==x){
            out+=trees[v][cur].st;
            return out;
        }
        if(trees[v][2*cur].nd>x) cur*=2;
        else{
            x-=trees[v][2*cur].nd;
            out+=trees[v][2*cur].st;
            cur=2*cur+1;
        }
    }
    return out;
}
void get_out(int v, int k){
    odw[v]=1;
    for(auto w:grf[v]){
        if(odw[w]) continue;
        get_out(w, k);
    }
    tmpX.clear(); tmpY.clear();
    int diff = (int)inp[v].size()-k;
    ll smY = get_y(v, k);
    int Y = (int)tmpY.size(); Y--;
    int X = (int)inp[v].size()-Y;
    if(v!=0) X--; 
    for(int i=0; i<=Y; i++){
        smY+=tmpY[i];
        if(X+i<diff-1) continue;
        Dp[v][1]=min(Dp[v][1], get_sm_x(v, diff-i-1)+smY+C[v]);
        if(X+i<diff) continue;
        Dp[v][0]=min(Dp[v][0], get_sm_x(v, diff-i)+smY);
        Dp[v][1]=min(Dp[v][1], get_sm_x(v, diff-i)+smY-tmpY[i]+C[v]);
    }
}
ll lg(int x){
    int out=0;
    while(x>0){
        out++;
        x/=2;
    }
    return out;
}
void init_tree(int v){
    for(int i=0; i<2*base[v]; i++) trees[v].pb({0, 0});
}
void upd_v(int i, int v, ll x){
    v+=base[i];
    trees[i][v].st=x;
    if(trees[i][v].st==0) trees[i][v].nd=0;
    else trees[i][v].nd=1;
    v/=2;
    while(v>0){
        trees[i][v].st=trees[i][2*v].st+trees[i][2*v+1].st;
        trees[i][v].nd=trees[i][2*v].nd+trees[i][2*v+1].nd;
        v/=2;
    }
}
vector<ll> minimum_closure_costs(int N, vector<int> U, vector<int> V, vector<int> W) {
    //PREPROCES
    int n=N;
    for(int i=0; i<n-1; i++){
        inp[U[i]].pb(V[i]);
        inp[V[i]].pb(U[i]);
    }
    for(int i=0; i<n; i++) Dp[i][0]=Dp[i][1]=INF;
    for(int i=0; i<n; i++) Vdeg[(int)inp[i].size()].pb(i);
    set_pre(0, 0);
    for(int i=0; i<n-1; i++){
        if(pre[U[i]]<pre[V[i]]) C[V[i]] = W[i];
        else C[U[i]] = W[i];
    }
    C[0] = INF;
    base[0] = (1<<lg((int)inp[0].size())); 
    for(int i=1; i<n; i++) base[i] = (1<<(lg((int)inp[i].size())));
    for(int v=0; v<n; v++){
        init_tree(v);
        vector<pair<ll, int>> wagi;
        for(auto w:inp[v]){
            if(pre[w]<pre[v]) continue;
            wagi.pb({C[w], w});
        }
        sort(wagi.begin(), wagi.end());
        for(int i=0; i<(int)wagi.size(); i++){
            upd_v(v, i, wagi[i].st);
            idx[wagi[i].nd] = i;
        }
    }
    //cout << get_sm_x(0, 2) << '\n';
    //for(int i=0; i<2*base[0]; i++) cout << trees[0][i].st << ' ' << trees[0][i].nd << "  ";
    //cout << '\n';
    for(int i=0; i<n; i++) sort(inp[i].begin(), inp[i].end(), comp);
    //WYNIK
    vector<pair<int, int>> Vert;
    vector<ll> WYNIK;
    for(int k=n-1; k>=0; k--){
        ll out=0;
        for(auto v:Vdeg[k+1]){
            Vert.pb({pre[v], v});
            if(v!=0) upd_v(par[v], idx[v], 0);
            for(auto w:inp[v]){
                if(inp[w].size()>=k+1) grf[v].pb(w);
                if(inp[w].size()>k+1) grf[w].pb(v);
            }
        }
        sort(Vert.begin(), Vert.end());
        for(auto Ve:Vert){
            int v=Ve.nd;
            if(odw[v]) continue;
            get_out(v, k);
            out+=min(Dp[v][0], Dp[v][1]);
        }
        //if(k==2) for(int i=0; i<n; i++) cout << Dp[i][0] << ' ' << Dp[i][1] << '\n';
        WYNIK.pb(out);
        //CZYSZCZENIE
        for(auto v:Vert){
            odw[v.nd]=0;
            Dp[v.nd][0]=Dp[v.nd][1]=INF;
        }
    }
    reverse(WYNIK.begin(), WYNIK.end());
    return WYNIK;
}
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... |