Submission #1234490

#TimeUsernameProblemLanguageResultExecution timeMemory
1234490nicolo_010Werewolf (IOI18_werewolf)C++20
100 / 100
828 ms101892 KiB
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include "werewolf.h"
using namespace std;
using ll  = long long;
using pii = pair<int, int>;
#define rep(i, k, n) for (int i = k; i < n; i++)
template<typename T>
using v = vector<T>;
const int INF = 1e9;

struct DSU {
    v<int> parent;

    DSU(int n) {
        parent.resize(n);
        rep(i, 0, n) parent[i] = i;
    }

    int find(int n) {
        return (parent[n] == n ? n : parent[n] = find(parent[n]));
    }

    void join(int a, int b, v<pii>&tree) {
        a = find(a);
        b = find(b);
        if (a != b) {
            int p = parent.size();
            parent[a] = parent[b] = p;
            parent.push_back(p);
            tree.push_back({a, b});
        }
    }
};

int t = 0;

pair<int, int> dfs(v<pii> &tree, int u, int N) {
    if (u < N) {
        tree[u] = {t, t};
        t++;
    }
    else {
        pii A = dfs(tree, tree[u].first, N);
        pii B = dfs(tree,tree[u].second, N);
        tree[u].first = min(A.first, B.first);
        tree[u].second = max(A.second, B.second);
    }
    return tree[u];
}

v<pii> points;

struct SegTree {
    v<v<int>> tree;
    v<v<int>> pts;
    SegTree(int n) {
        tree.assign(4*n, {});
        pts.resize(n);
        rep(i, 0, n) {
            pts[points[i].first].push_back(points[i].second);
        }
        rep(i, 0, n) {
            sort(pts[i].begin(), pts[i].end());
        }
        build(1, 0, n-1);
    }

    void build(int p, int l, int r) {
        if (l == r) {
            tree[p] = pts[l];
        }
        else {
            build(2*p, l, (l+r)/2);
            build(2*p+1, (l+r)/2+1, r);
            merge(tree[2*p].begin(), tree[2*p].end(),
                tree[2*p+1].begin(), tree[2*p+1].end(),
                back_inserter(tree[p]));
        }
    }

    int query(int p, int l, int r, int xl, int xr, int yl, int yr) {
        if (l > xr || r < xl) return 0;
        if (xl <= l && r <= xr)  {
            auto it = lower_bound(tree[p].begin(), tree[p].end(), yl) - tree[p].begin();
            auto it2 = upper_bound(tree[p].begin(), tree[p].end(), yr) - tree[p].begin();
            return it2 - it;
        }
        else {
            int m = (l+r)/2;
            int i1 = query(2*p, l, m, xl, xr, yl, yr);
            int i2 = query(2*p+1, m+1, r, xl, xr, yl, yr);
            return i1 + i2;
        }
    }

};

v<int> check_validity(int N, v<int> X, v<int> Y, v<int> S, v<int> E, v<int> L, v<int> R) {
    int M = X.size();
    int Q = L.size();
    L.push_back(0);
    R.push_back(N-1);
    S.push_back(0);
    E.push_back(0);
    v<pii> Lorder(Q+1);
    v<pii> Rorder(Q+1);
    rep(i, 0, Q+1) {
        Lorder[i] = {L[i], i};
        Rorder[i] = {R[i], i};
    }
    v<pii> vL(Q);
    v<pii> vR(Q);


    //vL recognition
    sort(Lorder.begin(), Lorder.end(), greater<>());
    DSU dsuL(N);
    v<pair<int, pii>> edgesL(M);
    rep(i, 0, M) {
        edgesL[i] = {min(X[i], Y[i]), {X[i], Y[i]}};
    }
    sort(edgesL.begin(), edgesL.end(), greater<>());
    int j = 0;
    v<int> leadL(Q+1);
    v<pii> treeL(N);
    rep(i, 0, Q+1) {
        while (j < M && edgesL[j].first >= Lorder[i].first) {
            dsuL.join(edgesL[j].second.first, edgesL[j].second.second, treeL);
            //cout << i << " " << edgesL[j].second.first << " " << edgesL[j].second.second << endl;
            j++;
        }
        //cout << i << " " << S[Lorder[i].second] << " " << dsuL.parent[6 ] << " " << dsuL.parent.size() << endl;
        leadL[Lorder[i].second] = dsuL.find(S[Lorder[i].second]);
    }
    t = 0;
    dfs(treeL, treeL.size()-1, N);
    rep(i, 0, Q) {
        vL[i] = treeL[leadL[i]];
    }
    //vR recognition
    sort(Rorder.begin(), Rorder.end());
    DSU dsuR(N);
    v<pair<int, pii>> edgesR(M);
    rep(i, 0, M) {
        edgesR[i] = {max(X[i], Y[i]), {X[i], Y[i]}};
    }
    sort(edgesR.begin(), edgesR.end());
    j = 0;
    v<int> leadR(Q+1);
    v<pii> treeR(N);
    rep(i, 0, Q+1) {
        while (j < M && edgesR[j].first <= Rorder[i].first) {
            dsuR.join(edgesR[j].second.first, edgesR[j].second.second, treeR);
            j++;
        }
        leadR[Rorder[i].second] = dsuR.find(E[Rorder[i].second]);
    }
    t = 0;
    dfs(treeR, treeR.size()-1, N);
    rep(i, 0, Q) {
        vR[i] = treeR[leadR[i]];
    }
    //Query preprocessing

    points.resize(N);
    rep(i, 0, N) {
        points[i] = {treeL[i].first, treeR[i].first};
    }
    sort(points.begin(), points.end());
    SegTree st(N);
    v<int> ans(Q);
    rep(i, 0, Q) {
        int que = st.query(1, 0, N-1, vL[i].first, vL[i].second, vR[i].first, vR[i].second);
        //cout << que << endl;
        ans[i] = que > 0;
    }
    return ans;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...