답안 #387550

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
387550 2021-04-09T01:21:42 Z rama_pang Road Construction (JOI21_road_construction) C++17
5 / 100
10000 ms 2097156 KB
#include <bits/stdc++.h>
using namespace std;

using lint = long long;
const lint inf = 1e18;

namespace Persistent {
  struct Node {
    int sum = 0;
    int lc = 0;
    int rc = 0;
  };

  const int MAX_SIZE = 2e7;

  int node_cnt = 1;
  array<Node, MAX_SIZE> node;

  int NewNode() {
    return node_cnt++;
  }

  int CopyNode(int n) {
    node[node_cnt] = node[n];
    return node_cnt++;
  }

  int Build(int tl, int tr) {
    int n = NewNode();
    if (tl == tr) return n;
    int md = (tl + tr) / 2;
    node[n].lc = Build(tl, md);
    node[n].rc = Build(md + 1, tr);
    return n;
  }

  int Update(int n, int tl, int tr, int p, int x) {
    n = CopyNode(n);
    if (tl == tr) {
      node[n].sum += x;
      return n;
    }
    int md = (tl + tr) / 2;
    node[n].sum += x;
    if (p <= md) {
      node[n].lc = Update(node[n].lc, tl, md, p, x);
    } else {
      node[n].rc = Update(node[n].rc, md + 1, tr, p, x);
    }
    return n;
  }

  int Query(int n, int tl, int tr, int l, int r) {
    if (tl > r || l > tr || tl > tr || l > r) return 0;
    if (l <= tl && tr <= r) return node[n].sum;
    int md = (tl + tr) / 2;
    return Query(node[n].lc, tl, md, l, r) + Query(node[n].rc, md + 1, tr, l, r);
  }
};

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);

  int N, K;
  cin >> N >> K;
  vector<lint> X(N), Y(N);
  vector<lint> coordX = {-inf, inf}, coordY = {-inf, inf};
  for (int i = 0; i < N; i++) {
    cin >> X[i] >> Y[i];
    tie(X[i], Y[i]) = pair(X[i] + Y[i], X[i] - Y[i]);
    coordX.emplace_back(X[i]);
    coordY.emplace_back(Y[i]);
  }

  sort(begin(coordX), end(coordX));
  sort(begin(coordY), end(coordY));
  coordX.resize(unique(begin(coordX), end(coordX)) - begin(coordX));
  coordY.resize(unique(begin(coordY), end(coordY)) - begin(coordY));

  vector<int> ord(N);
  iota(begin(ord), end(ord), 0);
  sort(begin(ord), end(ord), [&](int i, int j) { return X[i] < X[j]; });

  vector<int> tree(coordX.size());
  int prv = tree[0] = Persistent::Build(0, int(coordY.size()) - 1);

  for (auto i : ord) {
    int xid = lower_bound(begin(coordX), end(coordX), X[i]) - begin(coordX);
    int yid = lower_bound(begin(coordY), end(coordY), Y[i]) - begin(coordY);
    tree[xid] = Persistent::Update(prv, 0, int(coordY.size()) - 1, yid, 1);
    prv = tree[xid];
  }

  // for (int i = 0; i < N; i++) {
  //   cout << X[i] << ' ' << Y[i] << '\n';
  // }
  // for (int i = 0; i < coordX.size(); i++) {
  //   for (int j = 0; j < coordY.size(); j++) {
  //     cout << Persistent::Query(tree[i], 0, int(coordY.size()) - 1, j, j) << ' ';
  //   }
  //   cout << '\n';
  // }

  const auto Count = [&](lint dist) -> int {
    lint res = 0;
    for (int i = 0; i < N; i++) {
      int xlo = lower_bound(begin(coordX), end(coordX), X[i] - dist) - begin(coordX);
      int xhi = upper_bound(begin(coordX), end(coordX), X[i] + dist) - begin(coordX) - 1;
      int ylo = lower_bound(begin(coordY), end(coordY), Y[i] - dist) - begin(coordY);
      int yhi = upper_bound(begin(coordY), end(coordY), Y[i] + dist) - begin(coordY) - 1;
      res += Persistent::Query(tree[xhi], 0, int(coordY.size()) - 1, ylo, yhi);
      res -= Persistent::Query(tree[xlo - 1], 0, int(coordY.size()) - 1, ylo, yhi);
    }
    return res - N;
  };

  const auto Generate = [&](lint dist) -> vector<lint> {
    int sz = coordX.size();
    vector<vector<pair<lint, int>>> tree(2 * sz); // (Y, index)
    for (int i = 0; i < N; i++) {
      int xid = lower_bound(begin(coordX), end(coordX), X[i]) - begin(coordX);
      tree[sz + xid].emplace_back(Y[i], i);
    }
    for (int i = sz; i < sz + sz; i++) {
      sort(begin(tree[i]), end(tree[i]));
    }
    for (int i = sz - 1; i > 0; i--) {
      merge(begin(tree[i * 2]), end(tree[i * 2]), begin(tree[i * 2 + 1]), end(tree[i * 2 + 1]), back_inserter(tree[i]));
    }

    vector<pair<int, int>> pairs;
    for (int i = 0; i < N; i++) {
      int xlo = lower_bound(begin(coordX), end(coordX), X[i] - dist) - begin(coordX);
      int xhi = upper_bound(begin(coordX), end(coordX), X[i] + dist) - begin(coordX) - 1;
      for (xlo += sz, xhi += sz + 1; xlo < xhi; xlo /= 2, xhi /= 2) {
        if (xlo & 1) {
          auto it = lower_bound(begin(tree[xlo]), end(tree[xlo]), pair(Y[i] - dist, -1));
          while (it != end(tree[xlo]) && it->first <= Y[i] + dist) {
            pairs.emplace_back(i, it->second);
            it++;
          }
          xlo++;
        }
        if (xhi & 1) {
          xhi--;
          auto it = lower_bound(begin(tree[xhi]), end(tree[xhi]), pair(Y[i] - dist, -1));
          while (it != end(tree[xhi]) && it->first <= Y[i] + dist) {
            pairs.emplace_back(i, it->second);
            it++;
          }
        }
      }
    }

    vector<lint> res;
    for (auto [i, j] : pairs) {
      if (i != j) {
        res.emplace_back(max(abs(X[i] - X[j]), abs(Y[i] - Y[j])));
      }
    }
    return res;
  };

  lint lo = 0, hi = 1e10;
  while (lo < hi) {
    lint md = (lo + hi) / 2;
    if (Count(md) >= 2 * K) {
      hi = md;
    } else {
      lo = md + 1;
    }
  }

  vector<lint> ans = Generate(lo - 1);
  while (ans.size() < 2 * K) {
    ans.emplace_back(lo);
  }

  sort(begin(ans), end(ans));
  assert(ans.size() == 2 * K);
  for (int i = 0; i < K; i++) {
    assert(ans[i * 2] == ans[i * 2 + 1]);
    cout << ans[i * 2] << '\n';
  }
  return 0;
}

Compilation message

road_construction.cpp: In function 'int main()':
road_construction.cpp:176:21: warning: comparison of integer expressions of different signedness: 'std::vector<long long int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  176 |   while (ans.size() < 2 * K) {
      |          ~~~~~~~~~~~^~~~~~~
In file included from /usr/include/c++/9/cassert:44,
                 from /usr/include/x86_64-linux-gnu/c++/9/bits/stdc++.h:33,
                 from road_construction.cpp:1:
road_construction.cpp:181:21: warning: comparison of integer expressions of different signedness: 'std::vector<long long int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  181 |   assert(ans.size() == 2 * K);
      |          ~~~~~~~~~~~^~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 100 ms 10936 KB Output is correct
2 Correct 101 ms 10860 KB Output is correct
3 Correct 89 ms 10680 KB Output is correct
4 Correct 86 ms 10708 KB Output is correct
5 Correct 86 ms 10800 KB Output is correct
6 Correct 9 ms 592 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Execution timed out 10114 ms 1803008 KB Time limit exceeded
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 9248 ms 2097156 KB Execution killed with signal 9
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 9248 ms 2097156 KB Execution killed with signal 9
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 100 ms 10936 KB Output is correct
2 Correct 101 ms 10860 KB Output is correct
3 Correct 89 ms 10680 KB Output is correct
4 Correct 86 ms 10708 KB Output is correct
5 Correct 86 ms 10800 KB Output is correct
6 Correct 9 ms 592 KB Output is correct
7 Execution timed out 10055 ms 29344 KB Time limit exceeded
8 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 100 ms 10936 KB Output is correct
2 Correct 101 ms 10860 KB Output is correct
3 Correct 89 ms 10680 KB Output is correct
4 Correct 86 ms 10708 KB Output is correct
5 Correct 86 ms 10800 KB Output is correct
6 Correct 9 ms 592 KB Output is correct
7 Execution timed out 10114 ms 1803008 KB Time limit exceeded
8 Halted 0 ms 0 KB -