답안 #837460

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
837460 2023-08-25T11:09:59 Z QwertyPi 분수 공원 (IOI21_parks) C++17
0 / 100
1 ms 312 KB
#include "parks.h"
#include <bits/stdc++.h>
#define all(x) x.begin(), x.end()
using namespace std;

const int N_MAX = 2e5 + 11;

struct point{
    int x, y;
    bool operator< (const point& o) const {
        return x < o.x || (x == o.x && y < o.y);
    }
};

struct edge{
    int u, v;
};

int n;
map<point, int> mp;
vector<point> a;

struct DSU{
    int dsu[N_MAX];
    void init(int n){
        for(int i = 0; i < n; i++) dsu[i] = i;
    }
    int f(int x){ return x == dsu[x] ? x : dsu[x] = f(dsu[x]); }
    void g(int x, int y){ x = f(x), y = f(y); dsu[x] = y; }
} dsu;

vector<point> adj(int u, int v){
    assert(abs(a[u].x - a[v].x) + abs(a[u].y - a[v].y) == 2);
    if(a[u].x == a[v].x) return {{a[u].x - 1, (a[u].y + a[v].y) / 2}, {a[u].x + 1, (a[u].y + a[v].y) / 2}};
    else return {{(a[u].x + a[v].x) / 2, a[v].y - 1}, {(a[u].x + a[v].x) / 2, a[v].y + 1}};
}

vector<edge> construct_tree(){
    vector<edge> ans;
    dsu.init(n);
    vector<int> p; for(int i = 0; i < n; i++) p.push_back(i);
    sort(p.begin(), p.end(), [](int u, int v){ return a[u] < a[v]; });
    set<point> used;
    for(int j = 0; j < n; j++){
        int i = p[j];
        for(auto [dx, dy] : (a[i].x + a[i].y) % 4 ? vector<pair<int, int>>{{2, 0}, {0, 2}} : vector<pair<int, int>>{{0, -2}, {-2, 0}}){
            int nx = a[i].x + dx, ny = a[i].y + dy;
            if(mp.count({nx, ny})){
                int v = mp[{nx, ny}];
                ans.push_back({i, v});
                dsu.g(i, v);
                if(a[i].x == nx){
                    used.insert({nx - 1, (a[i].y + ny) / 2});
                }else{
                    used.insert({(a[i].x + nx) / 2, ny + 1});
                }
            }
        }
    }
    for(int j = 0; j < n; j++){
        int i = p[j];
        for(auto [dx, dy] : vector<pair<int, int>>{{0, -2}, {0, 2}, {2, 0}, {-2, 0}}){
            int nx = a[i].x + dx, ny = a[i].y + dy;
            if(mp.count({nx, ny})){
                int v = mp[{nx, ny}];
                vector<point> p = adj(i, v);
                if(used.count(p[0]) && used.count(p[1])) continue;
                if(dsu.f(i) != dsu.f(v)){
                    dsu.g(i, v);
                    ans.push_back({i, v});
                }
            }
        }
    }
    return ans;
}

vector<point> assign_benches(vector<edge> roads){
    vector<point> ans(roads.size());
    map<point, vector<int>> deg;
    set<point> done;
    for(int i = 0; i < (int) roads.size(); i++){
        int u = roads[i].u, v = roads[i].v;
        vector<point> p = adj(u, v);
        deg[p[0]].push_back(i);
        deg[p[1]].push_back(i);
    }
    vector<point> deg_0, deg_1;
    for(auto [p, v] : deg){
        if(v.size() == 0) deg_0.push_back(p);
        if(v.size() == 1) deg_1.push_back(p);
    }
    while(deg.size()){
        while(deg_0.size()) deg.erase(deg_0.back()), deg_0.pop_back();
        while(deg_1.size()){
            point v = deg_1.back(); deg_1.pop_back();
            if(done.count(v) || deg[v].empty()) continue; done.insert(v);

            int r = deg[v][0];
            ans[r] = v;

            int a = roads[r].u, b = roads[r].v;
            vector<point> p = adj(a, b);
            if(find(all(deg[p[0]]), r) != deg[p[0]].end()) deg[p[0]].erase(find(all(deg[p[0]]), r));
            if(find(all(deg[p[1]]), r) != deg[p[1]].end()) deg[p[1]].erase(find(all(deg[p[1]]), r));

            if(deg.count(p[0]) && deg[p[0]].size() == 0) deg_0.push_back(p[0]);
            if(deg.count(p[0]) && deg[p[0]].size() == 1) deg_1.push_back(p[0]);

            if(deg.count(p[1]) && deg[p[1]].size() == 0) deg_0.push_back(p[1]);
            if(deg.count(p[1]) && deg[p[1]].size() == 1) deg_1.push_back(p[1]);
        }
        if(deg.size()){
            auto [c, v] = *deg.begin(); 
            if(done.count(c) || deg[c].size() < 2){
                deg.erase(deg.begin());
                continue;
            }
            done.insert(c);
            int r = v[0];
            ans[r] = c;

            int a = roads[r].u, b = roads[r].v;
            vector<point> p = adj(a, b);

            deg[p[0]].clear();
            if(find(all(deg[p[1]]), r) != deg[p[1]].end()) deg[p[1]].erase(find(all(deg[p[1]]), r));

            if(deg[p[0]].size() == 0) deg_0.push_back(p[0]);
            if(deg[p[0]].size() == 1) deg_1.push_back(p[0]);

            if(deg[p[1]].size() == 0) deg_0.push_back(p[1]);
            if(deg[p[1]].size() == 1) deg_1.push_back(p[1]);
        }
    }
    return ans;
}

int construct_roads(vector<int> x, vector<int> y) {
    n = x.size();
    for(int i = 0; i < n; i++){
        a.push_back({x[i], y[i]});
        mp[a[i]] = i;
    }

    vector<edge> edges = construct_tree();
    if((int) edges.size() < n - 1) return 0;
    vector<point> benches = assign_benches(edges);
    vector<int> u(n - 1), v(n - 1), a(n - 1), b(n - 1);
    for(int i = 0; i < n - 1; i++){
        u[i] = edges[i].u, v[i] = edges[i].v;
        a[i] = benches[i].x, b[i] = benches[i].y;
    }
    build(u, v, a, b);
    return 1;
}

Compilation message

parks.cpp: In function 'std::vector<point> assign_benches(std::vector<edge>)':
parks.cpp:97:13: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
   97 |             if(done.count(v) || deg[v].empty()) continue; done.insert(v);
      |             ^~
parks.cpp:97:59: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
   97 |             if(done.count(v) || deg[v].empty()) continue; done.insert(v);
      |                                                           ^~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 0 ms 212 KB Output is correct
3 Correct 1 ms 312 KB Output is correct
4 Incorrect 1 ms 212 KB Edge between 2 and 1 appears more than once: appeared on positions 0 and 1
5 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 0 ms 212 KB Output is correct
3 Correct 1 ms 312 KB Output is correct
4 Incorrect 1 ms 212 KB Edge between 2 and 1 appears more than once: appeared on positions 0 and 1
5 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 0 ms 212 KB Output is correct
3 Correct 1 ms 312 KB Output is correct
4 Incorrect 1 ms 212 KB Edge between 2 and 1 appears more than once: appeared on positions 0 and 1
5 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 0 ms 212 KB Output is correct
3 Correct 1 ms 312 KB Output is correct
4 Incorrect 1 ms 212 KB Edge between 2 and 1 appears more than once: appeared on positions 0 and 1
5 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 0 ms 212 KB Output is correct
3 Correct 1 ms 312 KB Output is correct
4 Incorrect 1 ms 212 KB Edge between 2 and 1 appears more than once: appeared on positions 0 and 1
5 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 0 ms 212 KB Output is correct
3 Correct 1 ms 312 KB Output is correct
4 Incorrect 1 ms 212 KB Edge between 2 and 1 appears more than once: appeared on positions 0 and 1
5 Halted 0 ms 0 KB -