CodeForces - 958E3 Guard Duty (hard)
Description
平面上 \(2n\) 个点, \(A\) 类点和 \(B\) 类点各 \(n\) 点,在两类点之间连边,不能相交,输出方案。
\(n\le 10^4\)
Solution
分治。
每个分治区间按该区间最左下的点极角排序,枚举这个点连向哪个点,分治。
这样保证有合法解。
#include<bits/stdc++.h>
using namespace std;
template <class T> void read(T &x) {
x = 0; bool flag = 0; char ch = getchar(); for (; ch < '0' || ch > '9'; ch = getchar()) flag |= ch == '-';
for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - 48; flag ? x = ~x + 1 : 0;
}
//#pragma GCC diagnostic error "-std=c++14"
#define N 20010
#define rep(i, a, b) for (auto i = (a); i <= (b); ++i)
#define drp(i, a, b) for (auto i = (a); i >= (b); --i)
struct Point {
int x, y, id;
bool type;
}a[N], t;
int ans[N];
bool cmp1(const Point& a, const Point& b) {
return a.x < b.x || a.x == b.x && a.y < b.y;
}
bool cmp2(const Point& a, const Point& b) {
return 1.0 * (a.y - t.y) / (a.x - t.x) < 1.0 * (b.y - t.y) / (b.x - t.x);
}
void solve(int l, int r) {
if (l > r) return;
int c = min_element(a + l, a + r + 1, cmp1) - a;
swap(a[c], a[l]), t = a[l];
sort(a + l + 1, a + r + 1, cmp2);
int k = r, sum1 = 0, sum2 = 0;
for (; t.type == a[k].type || sum1 != sum2; k--)
if (a[k].type == t.type) sum1++; else sum2++;
a[k].type ? ans[t.id] = a[k].id : ans[a[k].id] = t.id;
solve(l + 1, k - 1), solve(k + 1, r);
}
int main() {
int n; read(n);
rep(i, 1, 2 * n) read(a[i].x), read(a[i].y), a[i].type = (a[i].id = i) > n;
rep(i, n + 1, 2 * n) a[i].id -= n;
solve(1, 2 * n);
rep(i, 1, n) printf("%d\n", ans[i]);
return 0;
}