답안 #920245

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
920245 2024-02-02T10:30:19 Z Gr47 공장들 (JOI14_factories) C++17
15 / 100
8000 ms 357924 KB
#include "factories.h"
#include <bits/stdc++.h>
using namespace std;

class CentroidDecomposition
{
private:
  int n;
  vector<bool> vis;
  vector<int> sz;
  const vector<vector<int>> &tree;

  int find_size(int v, int p = -1)
  {
    if (vis[v])
      return 0;
    sz[v] = 1;
    for (const int &x : tree[v])
      if (x != p)
        sz[v] += find_size(x, v);
    return sz[v];
  }

  int find_centroid(int v, int p, int cur_sz)
  {
    for (const int &x : tree[v])
      if (x != p)
        if (!vis[x] && sz[x] > (cur_sz / 2))
          return find_centroid(x, v, cur_sz);
    return v;
  }

  void init_centroid(int v, int p)
  {
    find_size(v);
    int c = find_centroid(v, -1, sz[v]);
    vis[c] = true;
    centroid_par[c] = p;
    if (p == -1)
      root = c;
    else
      centorid_tree[p].push_back(c);
    for (const int &x : tree[c])
      if (!vis[x])
        init_centroid(x, c);
  }

public:
  vector<vector<int>> centorid_tree;
  vector<int> centroid_par;
  int root;
  CentroidDecomposition(vector<vector<int>> &_tree) : tree(_tree)
  {
    root = 0;
    n = tree.size();
    centorid_tree.resize(n);
    vis.resize(n, false);
    sz.resize(n, 0);
    centroid_par.resize(n, -1);
    init_centroid(0, -1);
  }
};

struct segment
{
  long long sm = 0;
  bool def = true;
};

void init(segment &res, const long long &d)
{
  res.def = false;

  // TODO: initialize for one length segment
  res.sm = d;
}

segment combine(const segment &up, const segment &down)
{
  if (up.def)
    return down;
  if (down.def)
    return up;

  segment res;
  res.def = false;

  // TODO : Comine up and down segment
  res.sm = up.sm + down.sm;

  return res;
}

struct LCA
{
  int N;
  static const int D = 20;
  vector<vector<int>> table;
  vector<vector<segment>> seg;
  vector<int> depth;

  LCA(vector<vector<int>> &tree, map<pair<int, int>, long long> &edge)
  {
    N = tree.size();
    depth.assign(N, 0);
    table.assign(D, vector<int>(N, -1));
    seg.assign(D, vector<segment>(N));
    dfs(0, -1, tree, edge);
    for (int i = 1; i < D; i++)
    {
      for (int u = 0; u < N; u++)
      {
        if (table[i - 1][u] >= 0)
        {
          table[i][u] = table[i - 1][table[i - 1][u]];
          seg[i][u] = combine(seg[i - 1][table[i - 1][u]], seg[i - 1][u]);
        }
        else
          table[i][u] = -1;
      }
    }
  }

  void dfs(int u, int p, vector<vector<int>> &tree, map<pair<int, int>, long long> &edge)
  {
    table[0][u] = p;

    if (p != -1)
      init(seg[0][u], edge[make_pair(u, p)]);

    for (int v : tree[u])
    {
      if (v == p)
        continue;
      depth[v] = depth[u] + 1;
      dfs(v, u, tree, edge);
    }
  }

  int up(int u, int dist)
  {
    for (int i = D - 1; i >= 0; i--)
    {
      if ((dist & (1 << i)) > 0)
      {
        u = table[i][u];
        if (u == -1)
          return -1;
      }
    }
    return u;
  }

  int lca(int u, int v)
  {
    if (depth[u] < depth[v])
    {
      return lca(v, u);
    }

    int diff = depth[u] - depth[v];
    u = up(u, diff);
    if (u == v)
      return u;

    for (int i = D - 1; i >= 0; i--)
    {
      if (table[i][u] != table[i][v])
      {
        u = table[i][u];
        v = table[i][v];
      }
    }
    return table[0][u];
  }

  int distance(int u, int v)
  {
    int w = lca(u, v);
    return depth[u] + depth[v] - 2 * depth[w];
  }

  // get combined segment for [u(0),u(1),u(2),....u(up_walk)] where u(i+1) is parent of u(i) and u(0) = u
  segment combined_segment(int u, int up_walk)
  {
    segment res;

    for (int i = D - 1; i >= 0; i--)
    {
      if ((up_walk & (1 << i)) > 0)
      {
        if (res.def)
          res = seg[i][u];
        else
          res = combine(seg[i][u], res);
        u = table[i][u];
      }
    }
    return res;
  }

  segment path_segment(int u, int v)
  {
    int lc = lca(u, v);
    return combine(combined_segment(u, depth[u] - depth[lc]), combined_segment(v, depth[v] - depth[lc]));
  }
};

LCA *lca;
CentroidDecomposition *cd;
vector<long long> best;
const long long inf = 1e18;
void Init(int N, int A[], int B[], int D[])
{
  map<pair<int, int>, long long> edge;
  vector<vector<int>> tree(N);
  for (int i = 0; i < N - 1; i++)
  {
    tree[A[i]].push_back(B[i]);
    tree[B[i]].push_back(A[i]);
    edge[make_pair(A[i], B[i])] = D[i];
    edge[make_pair(B[i], A[i])] = D[i];
  }
  lca = new LCA(tree, edge);
  cd = new CentroidDecomposition(tree);
  best.resize(N, inf);
}

void add_node(int u)
{
  best[u] = 0;
  int p = u;
  while (p != cd->root)
  {
    p = cd->centroid_par[p];
    best[p] = min(best[p], lca->path_segment(u, p).sm);
  }
}

void rem_node(int u)
{
  best[u] = inf;
  int p = u;
  while (p != cd->root)
  {
    p = cd->centroid_par[p];
    best[p] = inf;
  }
}

long long get_min_dist(int u)
{
  long long ans = inf;
  int cur = u;
  while (cur != -1)
  {
    ans = min(ans, best[cur] + lca->path_segment(u, cur).sm);
    cur = cd->centroid_par[cur];
  }
  return ans;
}

long long Query(int S, int X[], int T, int Y[])
{
  long long ans = inf;
  for (int i = 0; i < S; i++)
    add_node(X[i]);
  for (int i = 0; i < T; i++)
    ans = min(ans, get_min_dist(Y[i]));
  for (int i = 0; i < S; i++)
    rem_node(X[i]);
  return ans;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 24 ms 17240 KB Output is correct
2 Correct 1000 ms 33616 KB Output is correct
3 Correct 2223 ms 33908 KB Output is correct
4 Correct 2133 ms 33740 KB Output is correct
5 Correct 2677 ms 34108 KB Output is correct
6 Correct 304 ms 33608 KB Output is correct
7 Correct 2237 ms 33896 KB Output is correct
8 Correct 2266 ms 33872 KB Output is correct
9 Correct 2645 ms 34132 KB Output is correct
10 Correct 315 ms 33620 KB Output is correct
11 Correct 2184 ms 33876 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 5 ms 16984 KB Output is correct
2 Correct 6774 ms 352220 KB Output is correct
3 Execution timed out 8053 ms 357924 KB Time limit exceeded
4 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 24 ms 17240 KB Output is correct
2 Correct 1000 ms 33616 KB Output is correct
3 Correct 2223 ms 33908 KB Output is correct
4 Correct 2133 ms 33740 KB Output is correct
5 Correct 2677 ms 34108 KB Output is correct
6 Correct 304 ms 33608 KB Output is correct
7 Correct 2237 ms 33896 KB Output is correct
8 Correct 2266 ms 33872 KB Output is correct
9 Correct 2645 ms 34132 KB Output is correct
10 Correct 315 ms 33620 KB Output is correct
11 Correct 2184 ms 33876 KB Output is correct
12 Correct 5 ms 16984 KB Output is correct
13 Correct 6774 ms 352220 KB Output is correct
14 Execution timed out 8053 ms 357924 KB Time limit exceeded
15 Halted 0 ms 0 KB -