Submission #430572

#TimeUsernameProblemLanguageResultExecution timeMemory
430572YarieCircle selection (APIO18_circle_selection)C++14
42 / 100
2839 ms128712 KiB
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#define x first
#define y second
#define all(v) v.begin(), v.end()
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<ll, ll> pii;
typedef vector<pii> vii;
typedef vector<bool> vb;

struct Circle{
    ll x, y, r;
    int ind;
};
bool operator<(Circle c1, Circle c2) {
    return c1.ind < c2.ind;
}

ll Dist(Circle c1, Circle c2) {
    return (c1.x - c2.x) * (c1.x - c2.x) + (c1.y - c2.y) * (c1.y - c2.y);
}

bool inters(Circle c1, Circle c2) {
    return Dist(c1, c2) <= (c1.r + c2.r) * (c1.r + c2.r);
}

int main() {
    int n;
    cin >> n;
    vector<Circle> circles(n);
    set<pii> ranges;
    vector<pair<pii, int>> sweep;
    bool subtask2 = true;
    bool subtask4 = true;
    map<pii, set<Circle>> grid;
    ll r = 0;
    for (int i = 0; i < n; i++) {
        cin >> circles[i].x >> circles[i].y >> circles[i].r;
        circles[i].ind = i + 1;
        if (r && r != circles[i].r) {
            subtask4 = false;
        }
        r = circles[i].r;
        grid[{circles[i].x / r, circles[i].y / r}].insert(circles[i]);
        if (circles[i].y) subtask2 = false;
        sweep.push_back({{circles[i].x, circles[i].y - circles[i].r}, i});
        sweep.push_back({{circles[i].x, circles[i].y + circles[i].r}, i});
        ranges.insert({circles[i].x - circles[i].r, i + 1});
        ranges.insert({circles[i].x + circles[i].r, i + 1});
    }
    sort(all(circles), [] (Circle c1, Circle c2) {
        if (c1.r == c2.r) return c1.ind < c2.ind;
        return c1.r > c2.r;
    });
    vi ans(n + 1);
    if (subtask4) {
        for (auto c : circles) {
            if (ans[c.ind]) continue;
            int x = c.x / r - 2;
            int y = c.y / r - 2;
            for (int i = x; i < x + 5; i++) {
                for (int j = y; j < y + 5; j++) {
                    auto it1 = grid.find({i, j});
                    if (it1 == grid.end()) continue;
                    for (auto it = it1->y.begin(); it != it1->y.end();) {
                        if (inters(c, *it)) {
                            ans[it->ind] = c.ind;
                            it = it1->y.erase(it);
                        } else {
                            it++;
                        }
                    }
                }
            }
        }
    }
    if (n <= 5000) {
        sort(all(circles), [] (Circle c1, Circle c2) {
            if (c1.r == c2.r) return c1.ind < c2.ind;
            return c1.r > c2.r;
        });
        for (int i = 0; i < n; i++) {
            Circle c = circles[i];
            if (ans[c.ind]) continue;
            ans[c.ind] = c.ind;
            for (int j = i + 1; j < n; j++) {
                if (!ans[circles[j].ind] && inters(circles[j], c)) {
                    ans[circles[j].ind] = c.ind;
                }
            }
        }
        for (int i = 1; i <= n; i++) cout << (ans[i] ? ans[i] : i) << " ";
        return 0;
    }
    if (subtask2) {
        sort(all(circles), [] (Circle c1, Circle c2) {
            if (c1.r == c2.r) return c1.ind < c2.ind;
            return c1.r > c2.r;
        });
        for (auto c : circles) {
            if (ans[c.ind]) continue;
            ans[c.ind] = c.ind;
            for (auto it = ranges.lower_bound({c.x - c.r, 0}); it != ranges.end() && it->x <= c.x + c.r; it = ranges.erase(it)) {
                if (!ans[it->y]) {
                    ans[it->y] = c.ind;
                }
            }
        }
        for (int i = 1; i <= n; i++) cout << (ans[i] ? ans[i] : i) << " ";
        return 0;
    }
    sort(all(sweep), [&] (pair<pii, int> p1, pair<pii, int> p2) {
        if (p1.x.y == p2.x.y) {
            bool a, b;
            a = p1.x.y < circles[p1.y].y;
            b = p2.x.y < circles[p2.y].y;
            return a > b;
        }
        return p1.x.y < p2.x.y;
    });
    set<pii> inside;
    for (auto p : sweep) {
        if (ans[p.y + 1]) continue;
        auto it = inside.insert({p.x.x, p.y});
        auto before = it.x, after = it.x;
        if (before != inside.begin()) {
            before--;
            if (inters(circles[before->y], circles[p.y])) {
                if (circles[before->y].r > circles[p.y].r || (circles[before->y].r == circles[p.y].r && before->y < p.y)) {
                    ans[before->y + 1] = ans[p.y + 1] = before->y + 1;
                } else {
                    ans[before->y + 1] = ans[p.y + 1] = p.y + 1;
                }
                inside.erase(it.x), inside.erase(before);
                continue;
            }
        }
        after++;
        if (after != inside.end()) {
            if (inters(circles[after->y], circles[p.y])) {
                if (circles[after->y].r > circles[p.y].r || (circles[after->y].r == circles[p.y].r && after->y < p.y)) {
                    ans[after->y + 1] = ans[p.y + 1] = after->y + 1;
                } else {
                    ans[after->y + 1] = ans[p.y + 1] = p.y + 1;
                }
                inside.erase(it.x), inside.erase(after);
                continue;
            }
        }
        if (!it.y) {
            inside.erase(it.x);
        }
    }
    for (int i = 1; i <= n; i++) cout << (ans[i] ? ans[i] : i) << " ";
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...