답안 #668372

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
668372 2022-12-03T17:51:38 Z 600Mihnea City Mapping (NOI18_citymapping) C++17
32 / 100
19 ms 568 KB
#include "citymapping.h"
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

ll ask(int i, int j)
{
  return get_distance(i + 1, j + 1);
}

void find_roads(int n, int q, int e_a[], int e_b[], int e_w[])
{
  vector<ll> dist0(n, 0);
  vector<int> ord;
  for (int i = 1; i < n; i++)
  {
    dist0[i] = ask(0, i);
    ord.push_back(i);
  }
  sort(ord.begin(), ord.end(), [&] (int i, int j) {return dist0[i] < dist0[j];});
  vector<int> deja = {0};
  vector<vector<int>> g(n);
  vector<int> sub(n), big(n), u(n), par(n);
  int top = 0;

  auto add_edge = [&] (int a, int b)
  {
 ///   cout << " add_edge : " << a << " " << b << "\n";
    e_a[top] = a + 1;
    e_b[top] = b + 1;
    e_w[top] = dist0[b] - dist0[a];
    g[a].push_back(b);
    top++;
  };

  function<void(int)> dfs = [&] (int a)
  {
    sub[a] = 1;
    if (g[a].empty())
    {
      u[a] = a;
      return;
    }
    assert(!g[a].empty());
    big[a] = g[a][0];
    for (auto &b : g[a])
    {
      dfs(b);
      par[b] = a;
      sub[a] += sub[b];
      if (sub[b] > sub[big[a]])
      {
        big[a] = b;
      }
    }
    u[a] = u[big[a]];
  };

  function<void(int, int)> locate = [&] (int root, int new_vertex)
  {
    if (sub[root] == 1)
    {
      add_edge(root, new_vertex);
      return;
    }
    assert(!g[root].empty());
    int b = u[root];
    assert(b != root);
    ll dist_b_v = ask(b, new_vertex);
    ll dist_b_r = dist0[b] - dist0[root];
    ll dist_v_r = dist0[new_vertex] - dist0[root];

    /**

    x + y = dist_b_r
    z + y = dist_b_v
    x + z = dist_v_r


    z = sum - dist_b_r
    x = sum - dist_b_v
    y - sum - dist_v_r

    **/

    ll sum_dub = (dist_b_v + dist_b_r + dist_v_r);
    assert(sum_dub % 2 == 0);
    ll sum = sum_dub / 2;

    ll z = sum - dist_b_r;
    ll x = sum - dist_b_v;
    ll y = sum - dist_v_r;

    assert(x + y + z == sum);
    assert(0 <= x);
    assert(0 <= y);
    assert(0 <= z);

    assert(x + y == dist_b_r);
    assert(z + y == dist_b_v);
    assert(x + z == dist_v_r);

    int fix_inainte = -1;

    /// scapa de astea!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   /// assert(x + y == ask(root, b));
   /// assert(x + z == ask(root, new_vertex));
   /// assert(z + y == ask(b, new_vertex));
    /// scapa de astea!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    if (y == 0)
    {
      add_edge(b, new_vertex);
      return;
    }

   // cout << "x = " << x << "\n";
   // cout << "y = " << y << "\n";
   // cout << "z = " << z << "\n";

    while (y > 0)
    {
      assert(b != root);
      y -= (dist0[b] - dist0[par[b]]);
      fix_inainte = b;
      b = par[b];
    }
    assert(y == 0);

    int mid_point = b;

    if (z == 0)
    {
      add_edge(mid_point, new_vertex);
      return;
    }
    assert(z > 0);
    ///cout << " = " << fix_inainte << " " << b << " " << root << "\n";
    assert(0 <= fix_inainte && fix_inainte < n);
    assert(par[fix_inainte] == b);

    if ((int) g[mid_point].size() == 1)
    {
      add_edge(mid_point, new_vertex);
      return;
    }

    assert((int) g[mid_point].size() == 2 || (int) g[mid_point].size() == 3);
    vector<int> oth;
    for (auto &vecin : g[mid_point])
    {
      if (vecin == fix_inainte)
      {
        continue;
      }
      oth.push_back(vecin);
    }
    assert((int) oth.size() == 1 || (int) oth.size() == 2);
    assert((int) oth.size() == (int) g[mid_point].size() - 1);
    if ((int) oth.size() == 1)
    {
      locate(oth[0], new_vertex);
      return;
    }
    assert((int) oth.size() == 2);
    if (ask(oth[0], new_vertex) < ask(oth[1], new_vertex))
    {
      locate(oth[0], new_vertex);
    }
    else
    {
      locate(oth[1], new_vertex);
    }
  };

  int nd = 0;

  for (auto &vertex : ord)
  {
   /// cout << " \t\t\t\t\t vertex = " << vertex << "\n";

    dfs(0);
    locate(0, vertex);

    nd++;
    assert(nd == top);
   /// cout << " \t\t\t\t\t\t\t\t\t" << e_a[nd - 1] << " " << e_b[nd - 1] << " " << e_w[nd - 1] << "\n";

    continue;
    return;

    for (int p = (int) deja.size() - 1; p >= 0; p--)
    {
      int oth = deja[p];
      if (ask(oth, vertex) + dist0[oth] == dist0[vertex])
      {
        add_edge(oth, vertex);
        break;
      }
    }
    deja.push_back(vertex);
  }
  if (0)
  {
    for (int i = 0; i < top; i++)
    {
      cout << " : " << e_a[i] << " " << e_b[i] << " " << e_w[i] << "\n";
    }
  }
  assert(top == n - 1);
}
# 결과 실행 시간 메모리 Grader output
1 Correct 18 ms 516 KB Correct: 2693 out of 500000 queries used.
2 Correct 15 ms 468 KB Correct: 2161 out of 500000 queries used.
3 Correct 16 ms 500 KB Correct: 4172 out of 500000 queries used.
4 Incorrect 15 ms 508 KB Reported list of edges differ from actual.
5 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 18 ms 516 KB Correct: 2693 out of 500000 queries used.
2 Correct 15 ms 468 KB Correct: 2161 out of 500000 queries used.
3 Correct 16 ms 500 KB Correct: 4172 out of 500000 queries used.
4 Incorrect 15 ms 508 KB Reported list of edges differ from actual.
5 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 16 ms 468 KB Correct: 2081 out of 12000 queries used.
2 Correct 18 ms 468 KB Correct: 2319 out of 12000 queries used.
3 Correct 19 ms 468 KB Correct: 2457 out of 12000 queries used.
4 Correct 16 ms 468 KB Correct: 2464 out of 12000 queries used.
5 Correct 17 ms 556 KB Correct: 2231 out of 12000 queries used.
# 결과 실행 시간 메모리 Grader output
1 Correct 16 ms 468 KB Correct: 2081 out of 12000 queries used.
2 Correct 18 ms 468 KB Correct: 2319 out of 12000 queries used.
3 Correct 19 ms 468 KB Correct: 2457 out of 12000 queries used.
4 Correct 16 ms 468 KB Correct: 2464 out of 12000 queries used.
5 Correct 17 ms 556 KB Correct: 2231 out of 12000 queries used.
6 Correct 17 ms 532 KB Correct: 2472 out of 12000 queries used.
7 Correct 17 ms 568 KB Correct: 2381 out of 12000 queries used.
8 Correct 16 ms 468 KB Correct: 2206 out of 12000 queries used.
9 Correct 19 ms 556 KB Correct: 2234 out of 12000 queries used.
10 Correct 19 ms 568 KB Correct: 2301 out of 12000 queries used.
# 결과 실행 시간 메모리 Grader output
1 Correct 18 ms 516 KB Correct: 2693 out of 500000 queries used.
2 Correct 15 ms 468 KB Correct: 2161 out of 500000 queries used.
3 Correct 16 ms 500 KB Correct: 4172 out of 500000 queries used.
4 Incorrect 15 ms 508 KB Reported list of edges differ from actual.
5 Halted 0 ms 0 KB -