Submission #412328

#TimeUsernameProblemLanguageResultExecution timeMemory
412328model_codeRoad Closures (APIO21_roads)C++17
100 / 100
245 ms47784 KiB
#include "roads.h"

#include <bits/stdc++.h>

const long long INF = 1e18;

struct Edge {
  int v, w;
  Edge(int _v, int _w): v(_v), w(_w) {}
};

class Fenwick {
  int size, n, logn;
  std::vector<int> counts;
  std::vector<long long> sums;
  std::vector<int> weights;

 public:
  void build(const std::vector<Edge> &edges) {
    size = 0;
    weights.resize(edges.size());
    for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
      weights[i] = edges[i].w;
    }
    std::sort(weights.begin(), weights.end());
    weights.erase(std::unique(weights.begin(), weights.end()), weights.end());

    n = weights.size();
    sums.assign(n, 0LL);
    counts.assign(n, 0);
    for (logn = 0; 1 << logn <= n; ++logn) {}
  }

  void add(int w) {
    int idx = lower_bound(weights.begin(), weights.end(), w) - weights.begin();
    assert(idx < static_cast<int>(weights.size()) && weights[idx] == w);
    ++size;
    for (int i = idx + 1; i <= n; i += i & -i) {
      ++counts[i - 1];
      sums[i - 1] += w;
    }
  }

  long long sumKMin(int k) {
    if (size < k) return INF;

    long long sum = 0;
    int cur = 0;
    for (int i = logn - 1; i >= 0; --i) {
      int nxt = cur + (1 << i);
      if (nxt >= n) continue;
      if (int cnt = counts[nxt - 1]; cnt <= k) {
        cur = nxt;
        k -= cnt;
        sum += sums[nxt - 1];
      }
    }
    return sum + 1LL * std::max(0, k) * weights[cur];
  }
};

std::vector<long long> minimum_closure_costs(int N,
    std::vector<int> U, std::vector<int> V, std::vector<int> W) {
  std::vector<std::vector<Edge>> adj(N);

  for (int i = 0; i < N - 1; ++i) {
    adj[U[i]].emplace_back(V[i], W[i]);
    adj[V[i]].emplace_back(U[i], W[i]);
  }

  std::vector<int> degrees(N);
  for (int i = 0; i < N; ++i) degrees[i] = adj[i].size();

  std::vector<int> nodes(N);
  std::vector<Fenwick> fenwicks(N);
  for (int u = 0; u < N; ++u) {
    nodes[u] = u;
    std::sort(adj[u].begin(), adj[u].end(), [&](Edge e, Edge f) {
      return degrees[e.v] > degrees[f.v];
    });
    fenwicks[u].build(adj[u]);
  }
  std::sort(nodes.begin(), nodes.end(), [&](int u, int v) {
    return degrees[u] > degrees[v];
  });

  std::vector<long long> ans(N);
  std::vector<std::vector<long long>> dp(N, std::vector<long long>(2));
  ans[0] = std::accumulate(W.begin(), W.end(), 0LL);
  for (int deg = 1; deg < N; ++deg) {
    while (!nodes.empty() && degrees[nodes.back()] <= deg) {
      for (auto [v, w] : adj[nodes.back()]) {
        fenwicks[v].add(w);
        while (!adj[v].empty() && degrees[adj[v].back().v] <= deg) {
          adj[v].pop_back();
        }
      }
      nodes.pop_back();
    }

    for (int u : nodes) {
      dp[u][0] = dp[u][1] = -1;
    }

    std::function<long long(int, int, int)> dfs = [&](int u, int p, int st) {
      if (~dp[u][st]) return dp[u][st];
      std::vector<int> deltas;
      long long total = 0;
      for (auto [v, w] : adj[u]) {
        if (v == p) continue;

        total += dfs(v, u, 1);
        deltas.push_back(dfs(v, u, 0) - dfs(v, u, 1) + w);
      }

      int remove = degrees[u] - deg - (u != p && st == 0);
      long long ret = total + fenwicks[u].sumKMin(remove);
      std::sort(deltas.begin(), deltas.end());
      for (int i = 0; i < static_cast<int>(deltas.size()); ++i) {
        total += deltas[i];
        ret = std::min(ret, total + fenwicks[u].sumKMin(remove - i - 1));
      }

      return dp[u][st] = ret;
    };

    for (int u : nodes) {
      if (dp[u][0] == -1) ans[deg] += dfs(u, u, 0);
    }
  }

  return ans;
}
#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...