Submission #1163375

#TimeUsernameProblemLanguageResultExecution timeMemory
1163375Math4Life2020Designated Cities (JOI19_designated_cities)C++20
100 / 100
896 ms69168 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long; using pii = pair<ll,ll>;

const ll Nm = 2e5+5;
bool found[Nm];
vector<array<ll,3>> adj[Nm]; //{x, forward edge cost, back edge cost}

vector<pii> q2; //queue for cost 2 vector: {cost, x}
pii dmax[Nm]; //{max distance, x to reach with}
ll sts[Nm]; //subtree size!
ll sumf = 0; //sum of forward edges

inline pii fz(pii p1, pii p2) {
    if (p1.first>p2.first) {
        return p1;
    }
    return p2;
}

void getq2(ll xc, ll prt) {
    dmax[xc]={0,xc};
    for (auto A0: adj[xc]) {
        ll y = A0[0];
        if (y!=prt && !found[y]) {
            getq2(y,xc);
            sumf += A0[2];
            dmax[xc]=fz(dmax[xc],{dmax[y].first+A0[1],dmax[y].second});
            q2.push_back({dmax[y].first+A0[1],dmax[y].second});
        }
    }
}

ll wsts(ll xc, ll prt) {
    sts[xc]=1;
    for (auto A0: adj[xc]) {
        ll y = A0[0];
        if (y!=prt && !found[y]) {
            sts[xc]+=wsts(y,xc);
        }
    }
    return sts[xc];
}

ll getctr(ll xc, ll prt, ll M) {
    for (auto A0: adj[xc]) {
        ll y = A0[0];
        if (y!=prt && !found[y]) {
            if (sts[y]*2>M) {
                return getctr(y,xc,M);
            }
        }
    }
    return xc;
}

//return: {cost 1, cost 2} vectors
pair<vector<ll>,vector<ll>> solve(ll xc, ll prt) { //current x, parent
    //cost 2 vector is easy: just greedy
    q2.clear();
    sumf = 0;
    getq2(xc,prt);
    ll cnump = 0;
    set<ll> xused;
    ll M = q2.size()+1;
    vector<ll> cost2(M+1,0);
    cost2[0]=sumf;
    sort(q2.rbegin(),q2.rend());
    for (pii p0: q2) {
        if (xused.find(p0.second)!=xused.end()) {
            continue;
        }
        cnump++;
        sumf += p0.first;
        cost2[cnump]=sumf;
        xused.insert(p0.second);
    }
    while (cnump<M) {
        cnump++;
        cost2[cnump]=sumf;
    }
    //now do cost 1 vector; this is harder...
    ll M1 = wsts(xc,prt);
    assert(M==M1);
    ll yc = getctr(xc,prt,M);
    //cout << "xc="<<xc<<", prt="<<prt<<" gives yc="<<yc<<"\n";
    found[yc]=1;
    vector<ll> ayc; //adjacent to yc
    vector<vector<ll>> ac1; //adjacent to yc: cost 1
    vector<vector<ll>> ac2; //adjacent to yc: cost 2
    ll cx = 1; ll cv = 0; //current # active, current value 
    ll sc02 = 0; //sum of cost2[0] for all
    vector<ll> cupd; //current update
    for (auto A0: adj[yc]) { //{y, forward, backward}
        ll zc = A0[0];
        if (!found[zc]) {
            auto A1 = solve(zc,yc);
            ayc.push_back(zc);
            ll L = A1.first.size();
            for (ll i=1;i<L;i++) {
                A1.second[i]+=A0[1];
                A1.first[i]+=A0[1];
            }
            for (ll i=0;i<L;i++) {
                A1.second[i]+=A0[2];
            }
            cv += A1.second[0];
            sc02 += A1.second[0];
            for (ll i=1;i<L;i++) {
                cupd.push_back(A1.second[i]-A1.second[i-1]);
            }
            ac1.push_back(A1.first);
            ac2.push_back(A1.second);
        }
    }
    //cout << "sc02="<<sc02<<"\n";
    ll FDEG = ayc.size();
    vector<ll> cost1(M+1,0);
    //process cost1
    sort(cupd.rbegin(),cupd.rend());
    cost1[1]=max(cost1[1],cv);
    for (ll ndv: cupd) {
        cx++;
        cv+=ndv;
        cost1[cx]=max(cost1[cx],cv);
    }
    for (ll T=0;T<FDEG;T++) {
        ll L = ac1[T].size();
        for (ll i=1;i<L;i++) {
            cost1[i]=max(cost1[i],ac1[T][i]-ac2[T][0]+sc02);
        }
    }
    if (FDEG>=2) {
        vector<pii> vupd0; //vector of updates (0->1)
        cx = 0;
        cv = 0;
        for (ll T=0;T<FDEG;T++) {
            cv += ac2[T][0];
            if (ac2[T].size()>=2) {
                vupd0.push_back({ac2[T][1]-ac2[T][0],T});
            }
        }
        sort(vupd0.rbegin(),vupd0.rend());
        if (vupd0.size()>=2) {
            cx = 2;
            cv += vupd0[0].first+vupd0[1].first;
            cost1[cx]=max(cost1[cx],cv);
            vector<ll> vupd1;
            for (ll TC=2;TC<vupd0.size();TC++) {
                vupd1.push_back(vupd0[TC].first);
            }
            for (ll T=0;T<FDEG;T++) {
                ll L = ac1[T].size();
                for (ll i=1;i<(L-1);i++) {
                    vupd1.push_back(ac2[T][i+1]-ac2[T][i]);
                }
            }
            sort(vupd1.rbegin(),vupd1.rend());
            for (ll x0: vupd1) {
                cx++;
                cv+=x0;
                cost1[cx]=max(cost1[cx],cv);
            }
        }
    }
    // cout << "xc,yc,prt="<<xc<<","<<yc<<","<<prt<<"\n";
    // for (ll x0: cost1) {
    //     cout << "cost1: "<<x0<<"\n";
    // }
    // for (ll x0: cost2) {
    //     cout << "cost2: "<<x0<<"\n";
    // }
    return {cost1,cost2};
}

int main() {
	ios_base::sync_with_stdio(false); cin.tie(0);
    ll N; cin >> N;
    for (ll i=0;i<N;i++) {
        found[i]=0;
    }
    ll SUMALL = 0;
    for (ll i=0;i<(N-1);i++) {
        ll a,b,c,d; cin >> a >> b >> c >> d;
        a--; b--;
        SUMALL += (c+d);
        adj[a].push_back({b,c,d});
        adj[b].push_back({a,d,c});
    }
    pair<vector<ll>,vector<ll>> FINANS = solve(0,-1);
    ll Q; cin >> Q;
    for (ll q=0;q<Q;q++) {
        ll e1; cin >> e1;
        cout << SUMALL-FINANS.first[e1] << "\n";
    } 
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...