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;
}
posted @ 2018-09-27 16:56 aziint 阅读(...) 评论(...) 编辑 收藏
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.