結果

問題 No.2436 Min Diff Distance
ユーザー ShirotsumeShirotsume
提出日時 2023-08-18 22:38:10
言語 C++23
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 512 ms / 2,000 ms
コード長 3,970 bytes
コンパイル時間 1,805 ms
コンパイル使用メモリ 133,900 KB
実行使用メモリ 25,772 KB
最終ジャッジ日時 2023-08-18 22:38:20
合計ジャッジ時間 9,691 ms
ジャッジサーバーID
(参考情報)
judge9 / judge11
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,376 KB
testcase_01 AC 1 ms
4,376 KB
testcase_02 AC 2 ms
4,380 KB
testcase_03 AC 512 ms
23,516 KB
testcase_04 AC 472 ms
22,708 KB
testcase_05 AC 504 ms
23,916 KB
testcase_06 AC 497 ms
22,756 KB
testcase_07 AC 468 ms
24,100 KB
testcase_08 AC 505 ms
22,956 KB
testcase_09 AC 1 ms
4,376 KB
testcase_10 AC 2 ms
4,380 KB
testcase_11 AC 282 ms
25,692 KB
testcase_12 AC 288 ms
25,772 KB
testcase_13 AC 338 ms
20,380 KB
testcase_14 AC 48 ms
5,704 KB
testcase_15 AC 457 ms
23,328 KB
testcase_16 AC 207 ms
13,128 KB
testcase_17 AC 428 ms
21,984 KB
testcase_18 AC 354 ms
21,812 KB
testcase_19 AC 406 ms
22,140 KB
testcase_20 AC 302 ms
13,984 KB
testcase_21 AC 116 ms
8,204 KB
testcase_22 AC 49 ms
5,596 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#line 1 "graph/test/manhattan_mst.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/manhattanmst"
#line 2 "graph/manhattan_mst.hpp"
#include <algorithm>
#include <map>
#include <numeric>
#include <tuple>
#include <vector>

// CUT begin
// Manhattan MST: 二次元平面上の頂点たちのマンハッタン距離による minimum spanning tree の O(N) 本の候補辺を列挙
// Complexity: O(N log N)
// output: [(weight_uv, u, v), ...]
// Verified: https://judge.yosupo.jp/problem/manhattanmst, https://www.codechef.com/problems/HKRMAN
// Reference:
// [1] H. Zhou, N. Shenoy, W. Nicholls,
//     "Efficient minimum spanning tree construction without Delaunay triangulation,"
//     Information Processing Letters, 81(5), 271-276, 2002.
template <typename T>
std::vector<std::tuple<T, int, int>> manhattan_mst(std::vector<T> xs, std::vector<T> ys) {
    const int n = xs.size();
    std::vector<int> idx(n);
    std::iota(idx.begin(), idx.end(), 0);
    std::vector<std::tuple<T, int, int>> ret;
    for (int s = 0; s < 2; s++) {
        for (int t = 0; t < 2; t++) {
            auto cmp = [&](int i, int j) { return xs[i] + ys[i] < xs[j] + ys[j]; };
            std::sort(idx.begin(), idx.end(), cmp);
            std::map<T, int> sweep;
            for (int i : idx) {
                for (auto it = sweep.lower_bound(-ys[i]); it != sweep.end(); it = sweep.erase(it)) {
                    int j = it->second;
                    if (xs[i] - xs[j] < ys[i] - ys[j]) break;
                    ret.emplace_back(std::abs(xs[i] - xs[j]) + std::abs(ys[i] - ys[j]), i, j);
                }
                sweep[-ys[i]] = i;
            }
            std::swap(xs, ys);
        }
        for (auto &x : xs) x = -x;
    }
    std::sort(ret.begin(), ret.end());
    return ret;
}
#line 4 "unionfind/unionfind.hpp"
#include <utility>
#line 6 "unionfind/unionfind.hpp"

// CUT begin
// UnionFind Tree (0-indexed), based on size of each disjoint set
struct UnionFind {
    std::vector<int> par, cou;
    UnionFind(int N = 0) : par(N), cou(N, 1) { iota(par.begin(), par.end(), 0); }
    int find(int x) { return (par[x] == x) ? x : (par[x] = find(par[x])); }
    bool unite(int x, int y) {
        x = find(x), y = find(y);
        if (x == y) return false;
        if (cou[x] < cou[y]) std::swap(x, y);
        par[y] = x, cou[x] += cou[y];
        return true;
    }
    int count(int x) { return cou[find(x)]; }
    bool same(int x, int y) { return find(x) == find(y); }
    std::vector<std::vector<int>> groups() {
        std::vector<std::vector<int>> ret(par.size());
        for (int i = 0; i < int(par.size()); ++i) ret[find(i)].push_back(i);
        ret.erase(std::remove_if(ret.begin(), ret.end(),
                                 [&](const std::vector<int> &v) { return v.empty(); }),
                  ret.end());
        return ret;
    }
};
#line 4 "graph/test/manhattan_mst.test.cpp"

#include <iostream>
using namespace std;

int main() {
    cin.tie(nullptr), ios::sync_with_stdio(false);

    int inf = 1000000000;
    int N;
    cin >> N;
    vector<int> xs(N), ys(N);
    vector<int> mini(N, inf), maxi(N, -inf);
    for (int i = 0; i < N; i++) cin >> xs[i] >> ys[i];
    UnionFind uf(N);
    long long weight = 0;
    vector<pair<int, int>> edges;
    for (auto [w, i, j] : manhattan_mst(xs, ys)) {
      mini[i] = min(mini[i], w);
      mini[j] = min(mini[j], w);
    }
    int maxx = -inf;
    int maxy = -inf;
    int minx = inf;
    int miny = inf;
    for(int i = 0; i < N; i++){
      int x = xs[i] + ys[i];
      int y = xs[i] - ys[i];
      maxx = max(maxx, x);
      minx = min(minx, x);
      maxy = max(maxy, y);
      miny = min(miny, y);
    }
    for(int i = 0; i < N; i++){
      int x = xs[i] + ys[i];
      int y = xs[i] - ys[i];
      maxi[i] = max({maxx - x, x - minx, maxy - y, y - miny});
    }

    int ans = inf;

    for(int i = 0; i < N; i++){
      ans = min(ans, maxi[i] - mini[i]);
    }
    cout << ans << '\n';
}
0