답안 #639006

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
639006 2022-09-08T07:53:17 Z tabr 늑대인간 (IOI18_werewolf) C++17
100 / 100
676 ms 120436 KB
#include <bits/stdc++.h>
using namespace std;
#ifdef tabr
#include "library/debug.cpp"
#else
#define debug(...)
#endif

// editorial

template <typename T>
struct forest {
    struct edge {
        int from;
        int to;
        T cost;
        edge(int _from, int _to, T _cost) : from(_from), to(_to), cost(_cost) {}
    };

    int n;
    vector<edge> edges;
    vector<vector<int>> g;
    vector<int> pv;
    vector<int> pe;
    vector<int> depth;
    vector<int> root;
    vector<int> sz;
    vector<int> order;
    vector<int> beg;
    vector<int> end;
    vector<T> dist;

    forest(int _n) : n(_n) {
        g = vector<vector<int>>(n);
        init();
    }

    void init() {
        pv = vector<int>(n, -1);
        pe = vector<int>(n, -1);
        depth = vector<int>(n, -1);
        root = vector<int>(n, -1);
        sz = vector<int>(n, 0);
        order = vector<int>();
        beg = vector<int>(n, -1);
        end = vector<int>(n, -1);
        dist = vector<T>(n, 0);
    }

    int add(int from, int to, T cost = 1) {
        int id = (int) edges.size();
        g[from].emplace_back(id);
        g[to].emplace_back(id);
        edges.emplace_back(from, to, cost);
        return id;
    }

    void do_dfs(int v) {
        beg[v] = (int) order.size();
        order.emplace_back(v);
        sz[v] = 1;
        for (int id : g[v]) {
            if (id == pe[v]) {
                continue;
            }
            edge e = edges[id];
            int to = e.from ^ e.to ^ v;
            pv[to] = v;
            pe[to] = id;
            depth[to] = depth[v] + 1;
            root[to] = (root[v] != -1 ? root[v] : to);
            dist[to] = dist[v] + e.cost;
            do_dfs(to);
            sz[v] += sz[to];
        }
        end[v] = (int) order.size();
    }

    void dfs(int v) {
        pv[v] = -1;
        pe[v] = -1;
        depth[v] = 0;
        root[v] = v;
        order.clear();
        dist[v] = 0;
        do_dfs(v);
    }

    void dfs_all() {
        init();
        for (int v = 0; v < n; v++) {
            if (depth[v] == -1) {
                dfs(v);
            }
        }
    }

    int h = -1;
    vector<vector<int>> p;

    inline void build_lca() {
        int max_depth = *max_element(depth.begin(), depth.end());
        h = 1;
        while ((1 << h) <= max_depth) {
            h++;
        }
        p = vector<vector<int>>(h, vector<int>(n));
        p[0] = pv;
        for (int i = 1; i < h; i++) {
            for (int j = 0; j < n; j++) {
                p[i][j] = (p[i - 1][j] == -1 ? -1 : p[i - 1][p[i - 1][j]]);
            }
        }
    }

    inline bool anc(int x, int y) {  // return x is y's ancestor or not
        return (beg[x] <= beg[y] && end[y] <= end[x]);
    }

    inline int go_up(int x, int up) {
        assert(h != -1);
        up = min(up, (1 << h) - 1);
        for (int i = h - 1; i >= 0; i--) {
            if (up & (1 << i)) {
                x = p[i][x];
                if (x == -1) {
                    break;
                }
            }
        }
        return x;
    }

    inline int lca(int x, int y) {
        assert(h != -1);
        if (anc(x, y)) {
            return x;
        }
        if (anc(y, x)) {
            return y;
        }
        for (int i = h - 1; i >= 0; i--) {
            if (p[i][x] != -1 && !anc(p[i][x], y)) {
                x = p[i][x];
            }
        }
        return p[0][x];
    }

    inline T distance(int x, int y) {
        return dist[x] + dist[y] - 2 * dist[lca(x, y)];
    }
};

struct dsu {
    vector<int> p;
    vector<int> sz;
    int n;

    dsu(int _n) : n(_n) {
        p = vector<int>(n);
        iota(p.begin(), p.end(), 0);
        sz = vector<int>(n, 1);
    }

    inline int get(int x) {
        if (p[x] == x) {
            return x;
        } else {
            return p[x] = get(p[x]);
        }
    }

    inline bool unite(int x, int y) {
        x = get(x);
        y = get(y);
        if (x == y) {
            return false;
        }
        p[x] = y;
        sz[y] += sz[x];
        return true;
    }

    inline bool same(int x, int y) {
        return (get(x) == get(y));
    }

    inline int size(int x) {
        return sz[get(x)];
    }

    inline bool root(int x) {
        return (x == get(x));
    }
};

struct segtree {
    using T = int;

    T e() {
        return (int) -2e9;
    }

    T op(T x, T y) {
        return max(x, y);
    }

    int n;
    int size;
    vector<T> node;

    segtree() : segtree(0) {}
    segtree(int _n) {
        build(vector<T>(_n, e()));
    }
    segtree(const vector<T> &v) {
        build(v);
    }

    void build(const vector<T> &v) {
        n = (int) v.size();
        if (n <= 1) {
            size = n;
        } else {
            size = 1 << (32 - __builtin_clz(n - 1));
        }
        node.resize(2 * size, e());
        for (int i = 0; i < n; i++) {
            node[i + size] = v[i];
        }
        for (int i = size - 1; i > 0; i--) {
            node[i] = op(node[2 * i], node[2 * i + 1]);
        }
    }

    void set(int p, T v) {
        assert(0 <= p && p < n);
        p += size;
        node[p] = v;  // update
        // node[p] += v;  // add
        while (p > 1) {
            p >>= 1;
            node[p] = op(node[2 * p], node[2 * p + 1]);
        }
    }

    T get(int l, int r) {
        assert(0 <= l && l <= r && r <= n);
        T vl = e();
        T vr = e();
        l += size;
        r += size;
        while (l < r) {
            if (l & 1) {
                vl = op(vl, node[l++]);
            }
            if (r & 1) {
                vr = op(node[--r], vr);
            }
            l >>= 1;
            r >>= 1;
        }
        return op(vl, vr);
    }

    T get(int p) {
        assert(0 <= p && p < n);
        return node[p + size];
    }
};

vector<int> check_validity(int n, vector<int> x, vector<int> y, vector<int> s, vector<int> e, vector<int> l, vector<int> r) {
    int m = (int) x.size();
    int q = (int) s.size();
    vector<vector<int>> g(n);
    for (int i = 0; i < m; i++) {
        g[x[i]].emplace_back(y[i]);
        g[y[i]].emplace_back(x[i]);
    }
    forest<int> g0(n), g1(n);
    dsu uf(n);
    for (int i = n - 1; i >= 0; i--) {
        for (int j : g[i]) {
            if (j > i && !uf.same(i, j)) {
                g0.add(i, uf.get(j));
                uf.unite(j, i);
            }
        }
    }
    g0.dfs(0);
    g0.build_lca();
    uf = dsu(n);
    for (int i = 0; i < n; i++) {
        for (int j : g[i]) {
            if (i > j && !uf.same(i, j)) {
                g1.add(i, uf.get(j));
                uf.unite(j, i);
            }
        }
    }
    g1.dfs(n - 1);
    g1.build_lca();
    vector<int> res(q);
    for (int i = 0; i < q; i++) {
        for (int j = g0.h - 1; j >= 0; j--) {
            if (g0.p[j][s[i]] >= l[i]) {
                s[i] = g0.p[j][s[i]];
            }
        }
        for (int j = g1.h - 1; j >= 0; j--) {
            if (g1.p[j][e[i]] <= r[i] && g1.p[j][e[i]] != -1) {
                e[i] = g1.p[j][e[i]];
            }
        }
    }
    vector<int> p(n);
    for (int i = 0; i < n; i++) {
        p[i] = g0.beg[g1.order[i]];
    }
    vector<int> pos(n);
    for (int i = 0; i < n; i++) {
        pos[p[i]] = i;
    }
    debug(g0.order);
    debug(g1.order);
    debug(p);
    segtree seg(n);
    vector<vector<int>> event(n);
    for (int i = 0; i < q; i++) {
        event[g0.end[s[i]] - 1].emplace_back(i);
    }
    for (int i = 0; i < n; i++) {
        seg.set(pos[i], i);
        for (int id : event[i]) {
            int t = seg.get(g1.beg[e[id]], g1.end[e[id]]);
            if (t >= g0.beg[s[id]]) {
                res[id] = 1;
            }
        }
    }
    return res;
}

#ifdef tabr
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    debug(check_validity(6, {5, 1, 1, 3, 3, 5}, {1, 2, 3, 4, 0, 2}, {4, 4, 5}, {2, 2, 4}, {1, 2, 3}, {2, 2, 4}));
    return 0;
}
#endif
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 340 KB Output is correct
2 Correct 1 ms 300 KB Output is correct
3 Correct 1 ms 304 KB Output is correct
4 Correct 0 ms 212 KB Output is correct
5 Correct 1 ms 340 KB Output is correct
6 Correct 1 ms 340 KB Output is correct
7 Correct 1 ms 340 KB Output is correct
8 Correct 1 ms 340 KB Output is correct
9 Correct 1 ms 340 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 340 KB Output is correct
2 Correct 1 ms 300 KB Output is correct
3 Correct 1 ms 304 KB Output is correct
4 Correct 0 ms 212 KB Output is correct
5 Correct 1 ms 340 KB Output is correct
6 Correct 1 ms 340 KB Output is correct
7 Correct 1 ms 340 KB Output is correct
8 Correct 1 ms 340 KB Output is correct
9 Correct 1 ms 340 KB Output is correct
10 Correct 6 ms 1752 KB Output is correct
11 Correct 5 ms 1752 KB Output is correct
12 Correct 5 ms 1592 KB Output is correct
13 Correct 5 ms 2004 KB Output is correct
14 Correct 5 ms 1852 KB Output is correct
15 Correct 6 ms 1844 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 550 ms 84000 KB Output is correct
2 Correct 571 ms 111568 KB Output is correct
3 Correct 527 ms 103564 KB Output is correct
4 Correct 513 ms 97860 KB Output is correct
5 Correct 467 ms 96184 KB Output is correct
6 Correct 507 ms 95632 KB Output is correct
7 Correct 514 ms 91616 KB Output is correct
8 Correct 524 ms 111504 KB Output is correct
9 Correct 426 ms 103564 KB Output is correct
10 Correct 396 ms 97588 KB Output is correct
11 Correct 409 ms 96664 KB Output is correct
12 Correct 455 ms 94996 KB Output is correct
13 Correct 595 ms 115096 KB Output is correct
14 Correct 666 ms 115064 KB Output is correct
15 Correct 571 ms 115288 KB Output is correct
16 Correct 621 ms 115112 KB Output is correct
17 Correct 513 ms 91380 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 340 KB Output is correct
2 Correct 1 ms 300 KB Output is correct
3 Correct 1 ms 304 KB Output is correct
4 Correct 0 ms 212 KB Output is correct
5 Correct 1 ms 340 KB Output is correct
6 Correct 1 ms 340 KB Output is correct
7 Correct 1 ms 340 KB Output is correct
8 Correct 1 ms 340 KB Output is correct
9 Correct 1 ms 340 KB Output is correct
10 Correct 6 ms 1752 KB Output is correct
11 Correct 5 ms 1752 KB Output is correct
12 Correct 5 ms 1592 KB Output is correct
13 Correct 5 ms 2004 KB Output is correct
14 Correct 5 ms 1852 KB Output is correct
15 Correct 6 ms 1844 KB Output is correct
16 Correct 550 ms 84000 KB Output is correct
17 Correct 571 ms 111568 KB Output is correct
18 Correct 527 ms 103564 KB Output is correct
19 Correct 513 ms 97860 KB Output is correct
20 Correct 467 ms 96184 KB Output is correct
21 Correct 507 ms 95632 KB Output is correct
22 Correct 514 ms 91616 KB Output is correct
23 Correct 524 ms 111504 KB Output is correct
24 Correct 426 ms 103564 KB Output is correct
25 Correct 396 ms 97588 KB Output is correct
26 Correct 409 ms 96664 KB Output is correct
27 Correct 455 ms 94996 KB Output is correct
28 Correct 595 ms 115096 KB Output is correct
29 Correct 666 ms 115064 KB Output is correct
30 Correct 571 ms 115288 KB Output is correct
31 Correct 621 ms 115112 KB Output is correct
32 Correct 513 ms 91380 KB Output is correct
33 Correct 672 ms 106812 KB Output is correct
34 Correct 243 ms 33488 KB Output is correct
35 Correct 648 ms 112168 KB Output is correct
36 Correct 590 ms 105144 KB Output is correct
37 Correct 676 ms 111428 KB Output is correct
38 Correct 648 ms 107364 KB Output is correct
39 Correct 626 ms 118612 KB Output is correct
40 Correct 664 ms 117096 KB Output is correct
41 Correct 536 ms 109920 KB Output is correct
42 Correct 530 ms 105176 KB Output is correct
43 Correct 654 ms 117648 KB Output is correct
44 Correct 633 ms 110780 KB Output is correct
45 Correct 516 ms 120436 KB Output is correct
46 Correct 524 ms 116636 KB Output is correct
47 Correct 584 ms 115224 KB Output is correct
48 Correct 574 ms 115000 KB Output is correct
49 Correct 576 ms 115260 KB Output is correct
50 Correct 570 ms 115084 KB Output is correct
51 Correct 625 ms 117468 KB Output is correct
52 Correct 629 ms 117600 KB Output is correct