DescriptionDescription
给定W×HW×H的平面。四个角落分别是四个出入口。
和nn个圆,用三元组表示。
和mm个人,用二元组表示。
求每个人不与任何圆相交可以到达哪些出入口。
SolutionSolution
考虑离线。
把O(n2)O(n2)个每两个圆之间的最短距离排序。
把mm个人的直径排序。
把个圆和上下左右四个边界看成节点。
考虑把圆按顺序加入图内,用并查集维护连通性。
分类讨论每两个边界联通后会导致四个角落连通性的变化。
using namespace std;
const double eps = 1e-4;
const int N = 2020;
const int M = 101010;
typedef long long ll;
inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
template<typename T>
inline void read(T &x) {
static char c; x = 0;
for (c = get(); c < '0' || c > '9'; c = get());
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
}
struct Point {
ll x, y, r;
inline double operator -(const Point &a) {
return (sqrt((x - a.x) * (x - a.x) + (y - a.y) * (y - a.y))) - r - a.r;
}
};
struct cpp {
ll x, id, r;
inline bool operator <(const cpp &a) const{
return r < a.r;
}
};
struct PPairs {
ll x, y;
double d;
inline bool operator <(const PPairs &a) const {
return d < a.d;
}
PPairs(double _d = 0, ll _x = 0, ll _y = 0):x(_x), y(_y), d(_d) {}
};
Point p[N];
cpp a[M];
PPairs d[N * N];
int n, m, w, h, p1, dnt;
int fa[N], rk[N];
int ans[M][5];
int mp[5][5];
inline int Fa(int x) {
return x == fa[x] ? x : fa[x] = Fa(fa[x]);
}
inline int Merge(int x, int y) {
static int f1, f2;
f1 = Fa(x); f2 = Fa(y);
if (f1 == f2) return false;
if (rk[f1] > rk[f2]) swap(f1, f2);
if (rk[f1] == rk[f2]) ++rk[f2];
fa[f1] = f2; return true;
}
inline void Link(int x, int y) {
mp[x][y] = mp[y][x] = 0;
}
// n + 1 up, n + 2 down, n + 3 left and n + 4 right
// 1 = bottom-left, 2 = bottom-right, 3 = top-right, 4 = top-left
int main(void) {
freopen("park.in", "r", stdin);
freopen("park.out", "w", stdout);
read(n); read(m);
read(w); read(h);
for (int i = 1; i <= n; i++) {
read(p[i].x); read(p[i].y); read(p[i].r);
}
for (int i = 1; i <= m; i++) {
read(a[i].r); read(a[i].x);
a[i].r *= 2; a[i].id = i;
}
for (int i = 1; i <= n; i++) {
d[++dnt] = PPairs(h - p[i].y - p[i].r, i, n + 1);
d[++dnt] = PPairs(p[i].y - p[i].r, i, n + 2);
d[++dnt] = PPairs(p[i].x - p[i].r, i, n + 3);
d[++dnt] = PPairs(w - p[i].x - p[i].r, i, n + 4);
for (int j = i + 1; j <= n; j++)
d[++dnt] = PPairs(fabs(p[j] - p[i]), i, j);
}
sort(d + 1, d + dnt + 1);
sort(a + 1, a + m + 1);
for (int i = 1; i <= n + 4; i++) fa[i] = i;
p1 = 1;
for (int i = 1; i <= 4; i++)
for (int j = 1; j <= 4; j++)
mp[i][j] = 1;
for (int i = 1; i <= m; i++) {
while (d[p1].d + eps < a[i].r && p1 <= dnt) {
Merge(d[p1].x, d[p1].y); ++p1;
}
if (Fa(n + 1) == Fa(n + 2)) {
Link(1, 2); Link(1, 3);
Link(4, 2); Link(4, 3);
}
if (Fa(n + 1) == Fa(n + 3)) {
Link(4, 1); Link(4, 2);
Link(4, 3);
}
if (Fa(n + 1) == Fa(n + 4)) {
Link(3, 1); Link(3, 2);
Link(3, 4);
}
if (Fa(n + 2) == Fa(n + 3)) {
Link(1, 2); Link(1, 3);
Link(1, 4);
}
if (Fa(n + 2) == Fa(n + 4)) {
Link(2, 1); Link(2, 3);
Link(2, 4);
}
if (Fa(n + 3) == Fa(n + 4)) {
Link(1, 3); Link(1, 4);
Link(2, 3); Link(2, 4);
}
for (int j = 1; j <= 4; j++)
ans[a[i].id][j] = mp[a[i].x][j];
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= 4; j++)
if (ans[i][j]) putchar('0' + j);
putchar('\n');
}
return 0;
}