Submission #522107

#TimeUsernameProblemLanguageResultExecution timeMemory
522107blueRoad Closures (APIO21_roads)C++17
100 / 100
409 ms166780 KiB
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;

using vi = vector<int>;
using vvi = vector<vi>;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using pii = pair<int, int>;
#define sz(x) int(x.size())

const int mx = 100'000;
const ll INF = 1'000'000'000'000'000'000LL;


int N;
vi U, V, W;

vi edge[mx];
vi deg(mx, 0);
vi deg_occ[mx];

vi depth(mx);
vi parent(mx, -1);

ll wt_sum = 0;

vi par_wt(mx);



void dfs1(int u, int p)
{
    for(int e: edge[u])
    {
        int v = U[e] + V[e] - u;
        int w = W[e];
        if(v == p) continue;

        par_wt[v] = w;

        depth[v] = depth[u] + 1;
        parent[v] = u;
        dfs1(v, u);
    }
}




struct segtree
{
    int l;
    int r;

    ll sm = 0;
    int ct = 0;

    segtree* left = NULL;
    segtree* right = NULL;

    segtree()
    {
        ;
    }

    segtree(int L, int R)
    {
        l = L;
        r = R;
        sm = 0;
        ct = 0;
    }

    void insert(int v)
    {
        // cerr << "enter insert\n";
        ct++;
        sm += v;
        if(l != r)
        {
            if(v <= (l+r)/2)
            {
                if(left == NULL) left = new segtree(l, (l+r)/2);
                left->insert(v);
            }
            else
            {
                if(right == NULL) right = new segtree((l+r)/2+1, r);
                right->insert(v);
            }
        }
        // cerr << "exit insert\n";
    }

    ll getsum(ll v)
    {
        // cerr << "enter getsum\n";
        if(v == 0) 
        {
            return 0;
        }
        else if(l == r)
        {
            return ll(l) * v;
        }
        else
        {
            // cerr << "case 3\n";
            if(left != NULL && left->ct >= v) return left->getsum(v);
            else return (left == NULL ? 0 : left->sm) + right->getsum(v - (left == NULL ? 0 : left->ct));
        }
        // cerr << "exit getsum\n";
    }
};


struct DS
{
    int curr_size = 0;

    segtree S = segtree(1, 1'000'000'000);

    ll minSum(int z)
    {
        if(z > curr_size) return INF;
        else if(z <= 0) return 0;
        else return S.getsum(z);
    }

    void insert(int v)
    {
        curr_size++;
        S.insert(v);
    }

    int size()
    {
        return curr_size;
    }
};


// struct DS
// {
//     multiset<ll> values;

//     ll minSum(int z)
//     {
//         if(z > sz(values)) return INF;

//         if(z <= 0) return 0;

//         int ct = 0;
//         ll res = 0;

//         for(ll v : values)
//         {
//             res += v;
//             ct++;
//             if(ct == z) break;
//         }

//         return res;
//     }

//     void insert(ll v) 
//     {
//         values.insert(v);
//     }

//     int size()
//     {
//         return sz(values);
//     }
// };







vll minimum_closure_costs(int N_, vi U_, vi V_, vi W_)
{   
    N = N_;
    U = U_;
    V = V_;
    W = W_;

    for(int e = 0; e < N-1; e++)
    {
        edge[U[e]].push_back(e);
        edge[V[e]].push_back(e);

        deg[U[e]]++;
        deg[V[e]]++;

        wt_sum += W[e];
    }

    for(int i = 0; i < N; i++)
        deg_occ[deg[i]].push_back(i);

    for(int i = 0; i < N; i++)
    {
        sort(edge[i].begin(), edge[i].end(), [] (int e, int f)
        {
            return deg[U[e]] + deg[V[e]] > deg[U[f]] + deg[V[f]];
        });
    }


    dfs1(0, -1);

    set<pii> it_list;

    for(int i = 0; i < N; i++) it_list.insert({-depth[i], i});


    vll res(N, 0);

    res[0] = wt_sum;

                     // root deg <= K-1
    vll dp0(N), dp1(N);
    //root deg <= K

    DS extra_edges[N];

    vi intdeg = deg;
    for(int i = 1; i < N; i++)
        intdeg[i]--;

    for(int k = 1; k < N; k++)
    {
        // cerr << "\n\n\n\n\n";
        // cerr << "k = " << k << '\n';
        for(int u: deg_occ[k]) //deg_occ[0] is empty
        {
            // cerr << "eliminating " << u << '\n';
            it_list.erase({-depth[u], u});
            for(int e : edge[u])
            {
                int v = U[e] + V[e] - u;
                int w = W[e];
                if(parent[v] != u)
                    extra_edges[v].insert(w);
                // cerr << "extra edges " << v << " -> insert " << w << '\n';
            }
        }

        for(auto p: it_list)
        {
            // cerr << "\n\n";
            int u = p.second;
            // cerr << "u = " << u << '\n';

            // cerr << "ee = ";
            // for(ll y : extra_edges[u].values) cerr << y << ' ';
                // cerr << '\n';

            dp0[u] = dp1[u] = INF;

            ll basicCost = 0;

            vector<ll> upgrades;

            for(auto e: edge[u])
            {
                int v = U[e] + V[e] - u;
                ll w = W[e];

                if(v == parent[u]) continue;

                if(deg[v] <= k) break;

                basicCost += dp1[v];
                upgrades.push_back(dp0[v] + w - dp1[v]);
            }

            sort(upgrades.begin(), upgrades.end());

            ll upgrade_total = 0;

            dp0[u] = min(dp0[u], basicCost + extra_edges[u].minSum(intdeg[u] - k));
            dp1[u] = min(dp1[u], basicCost + extra_edges[u].minSum(intdeg[u] - (k-1)));

            // cerr << "pre : " << dp0[u] << ' ' << dp1[u] << '\n';

            // cerr << basicCost << '\n';

            // cerr << "ee size = " << sz(extra_edges[u]) << ", query val = " << intdeg[u] - k << '\n';




            for(int cct = 0; cct < sz(upgrades); cct++)
            {
                // cerr << "cct = " << cct << '\n';
                upgrade_total += upgrades[cct];
                dp0[u] = min(dp0[u], basicCost + upgrade_total + extra_edges[u].minSum(intdeg[u] - k - (cct+1)));
                dp1[u] = min(dp1[u], basicCost + upgrade_total + extra_edges[u].minSum(intdeg[u] - (k-1) - (cct+1)));
                // cerr << "! " << intdeg[u] - k - (cct+1) << ' ' << intdeg[u] - (k-1) - (cct+1) << '\n';
                // cerr << cct << " , " << basicCost + upgrade_total + extra_edges[u].minSum(intdeg[u] - k - (cct+1)) << ' ' << basicCost + upgrade_total + extra_edges[u].minSum(intdeg[u] - (k-1) - (cct+1)) << '\n';
            }

            if(u == 0) 
            {
                    // cerr << "adding " << dp0[u] << " a to res " << k << '\n'; 
                res[k] += dp0[u];
            }
            else if(deg[parent[u]] <= k)
            {
                // cerr << "adding " << min(dp1[u], dp0[u] + par_wt[u]) << " b to res " << k << '\n'; 
                res[k] += min(dp1[u], dp0[u] + par_wt[u]);
            }

            // cerr << u << " : " << parent[u] << ' ' << dp0[u] << ' ' << dp1[u] << '\n';
        }
    }


    return res;
}
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...