Submission #257023

#TimeUsernameProblemLanguageResultExecution timeMemory
257023rama_pangPark (BOI16_park)C++14
100 / 100
756 ms33540 KiB
#include <bits/stdc++.h>
using namespace std;

class DisjointSet {
 public:
  vector<int> p;
  DisjointSet() {}
  DisjointSet(int sz) : p(sz) {
    iota(begin(p), end(p), 0);
  }
  void Clear() {
    iota(begin(p), end(p), 0);
  }
  int Find(int x) {
    return p[x] == x ? x : p[x] = Find(p[x]);
  }
  int Unite(int x, int y) {
    x = Find(x), y = Find(y);
    if (x != y) {
      p[x] = y;
      return 1;
    }
    return 0;
  }
  bool SameSet(int x, int y) {
    return Find(x) == Find(y);
  }
};

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

  int N, Q, H, W;
  cin >> N >> Q >> W >> H;
  vector<long long> X(N), Y(N), R(N);
  for (int i = 0; i < N; i++) {
    cin >> X[i] >> Y[i] >> R[i];
  }

  vector<long long> blocks(6, 1e18);
  // blocks[0] = cover left to down
  // blocks[1] = cover down to right
  // blocks[2] = cover right to up
  // blocks[3] = cover up to left
  // blocks[4] = cover left to right
  // blocks[5] = cover up to down

  auto GetSide = [&](long long x, long long y) {
    if (x < 0) return N + 0;
    if (y < 0) return N + 1;
    if (x > W) return N + 2;
    if (y > H) return N + 3;
    return -1;
  };

  vector<pair<long long, pair<int, int>>> edges;
  for (int i = 0; i < N; i++) {
    for (int j = i + 1; j < N; j++) {
      long long lo = 0, hi = 1e9;
      while (lo < hi) {
        long long md = (lo + hi) / 2;
        if ((X[i] - X[j]) * (X[i] - X[j]) + 
            (Y[i] - Y[j]) * (Y[i] - Y[j]) < 
            (R[i] + R[j] + 2ll * md) * (R[i] + R[j] + 2ll * md)) {
          hi = md;
        } else {
          lo = md + 1;
        }
      }
      edges.push_back({lo, {i, j}});
    }
  }
  
  auto GetX = [&](int i, long long md, int t) {
    if (t == 0) return X[i] - 2ll * md - R[i];
    if (t == 1) return X[i] + 2ll * md + R[i];
    return X[i];
  };

  auto GetY = [&](int i, long long md, int t) {
    if (t == 2) return Y[i] - 2ll * md - R[i];
    if (t == 3) return Y[i] + 2ll * md + R[i];
    return Y[i];
  };
  
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < 4; j++) {
      long long lo = 0, hi = 1e9;
      while (lo < hi) {
        long long md = (lo + hi) / 2;
        if (GetSide(GetX(i, md, j), GetY(i, md, j)) != -1) {
          hi = md;
        } else {
          lo = md + 1;
        }
      }
      edges.push_back({lo, {i, GetSide(GetX(i, lo, j), GetY(i, lo, j))}});
    }
  }

  DisjointSet D(N + 4);
  sort(begin(edges), end(edges));
  for (auto e : edges) {
    D.Unite(e.second.first, e.second.second);
    if (D.SameSet(N + 0, N + 1)) blocks[0] = min(blocks[0], e.first);
    if (D.SameSet(N + 1, N + 2)) blocks[1] = min(blocks[1], e.first);
    if (D.SameSet(N + 2, N + 3)) blocks[2] = min(blocks[2], e.first);
    if (D.SameSet(N + 3, N + 0)) blocks[3] = min(blocks[3], e.first);
    if (D.SameSet(N + 0, N + 2)) blocks[4] = min(blocks[4], e.first);
    if (D.SameSet(N + 1, N + 3)) blocks[5] = min(blocks[5], e.first);    
  }

  while (Q--) {
    int r, e;
    cin >> r >> e;
    e--;
    string ans;
    for (int i = 0; i < 4; i++) {
      long long b = min(blocks[e], blocks[i]);
      if (((e == 0 || e == 1) && (i == 2 || i == 3)) || ((i == 0 || i == 1) && (e == 2 || e == 3))) {
        b = min(b, blocks[4]);
      }
      if (((e == 0 || e == 3) && (i == 1 || i == 2)) || ((i == 0 || i == 3) && (e == 1 || e == 2))) {
        b = min(b, blocks[5]);
      }
      if (e == i || r < b) {
        ans.push_back('1' + i);
      }
    }
    cout << ans << "\n";
  }
  return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...