제출 #1346210

#제출 시각아이디문제언어결과실행 시간메모리
1346210MisterReaperPassport (JOI23_passport)C++20
100 / 100
448 ms233796 KiB
#include <bits/stdc++.h>

using i64 = long long;

#ifdef DEBUG
    #include "/home/ahmetalp/Desktop/Workplace/debug.h"
#else
    #define debug(...) void(23)
#endif

template<typename T>
bool chmin(T& a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

constexpr int max_N = int(2E5) + 5;
constexpr int LOG = std::__lg(max_N) + 1;
constexpr int inf = int(1E9);


template<typename F>
struct SparseTable {
    F fun;
    std::vector<int> logs;
    std::vector<std::vector<int>> mat;
    SparseTable(std::vector<int> v, F fun_) : fun(fun_) {
        int n = int(v.size());
        logs.assign(n + 1, -1);
        logs[0] = -1;
        for (int i = 1; i <= n; ++i) {
            logs[i] = logs[i >> 1] + 1;
        }
        mat.resize(logs[n] + 1);
        mat[0] = v;
        for (int i = 1; i <= logs[n]; ++i) {
            mat[i].resize(n - (1 << i) + 1);
            for (int j = 0; j + (1 << i) <= n; ++j) {
                mat[i][j] = std::min(mat[i - 1][j], mat[i - 1][j + (1 << (i - 1))], fun);
            }
        }
    }
    int get(int l, int r) {
        int lg = logs[r - l];
        return std::min(mat[lg][l], mat[lg][r - (1 << lg)], fun);
    }
};

int dis0[max_N * 2];
int disN[max_N * 2];
int dis[max_N * 2];
std::vector<std::pair<int, int>> adj[max_N * 2];
int roots[max_N];
int lc[max_N * 2];
int rc[max_N * 2];

int cur = 0;
int new_node() {
    return cur++;
}

int build(int l, int r) {
    if (l == r) {
        roots[l] = new_node();
        return roots[l];
    }
    int v = new_node();
    int mid = (l + r) >> 1;
    lc[v] = build(l, mid);
    rc[v] = build(mid + 1, r);
    adj[lc[v]].emplace_back(v, 0);
    adj[rc[v]].emplace_back(v, 0);
    return v;
}

void add_edge(int v, int l, int r, int L, int R, int x) {
    if (L == l && r == R) {
        adj[v].emplace_back(x, 1);
        return;
    }
    int mid = (l + r) >> 1;
    if (R <= mid) {
        add_edge(lc[v], l, mid, L, R, x);
    } else if (mid + 1 <= L) {
        add_edge(rc[v], mid + 1, r, L, R, x);
    } else {
        add_edge(lc[v], l, mid, L, mid, x);
        add_edge(rc[v], mid + 1, r, mid + 1, R, x);
    }
}

int N;
int Q;
int L[max_N];
int R[max_N];

std::queue<int> buckets[max_N];

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);

    std::cin >> N;

    for (int i = 0; i < N; ++i) {
        std::cin >> L[i] >> R[i];
        --L[i], --R[i];
    }

    int root = build(0, N - 1);

    for (int i = 0; i < N; ++i) {
        add_edge(root, 0, N - 1, L[i], R[i], roots[i]);
        // for (int j = L[i]; j <= R[i]; ++j) {
        //     adj[j].emplace_back(i);
        // }
    }

    std::fill(dis0, dis0 + 2 * N, inf);
    std::fill(disN, disN + 2 * N, inf);

    {
        dis0[roots[0]] = 0;
        buckets[0].emplace(roots[0]);
        for (int d = 0; d < max_N; ++d) {
            auto& que = buckets[d];
            while (!que.empty()) {
                auto v = que.front();
                que.pop();
                if (dis0[v] != d) {
                    continue;
                }
                for (auto[u, w] : adj[v]) {
                    if (chmin(dis0[u], dis0[v] + w)) {
                        buckets[dis0[u]].emplace(u);
                    }
                }
            }
        }
        disN[roots[N - 1]] = 0;
        buckets[0].emplace(roots[N - 1]);
        for (int d = 0; d < max_N; ++d) {
            auto& que = buckets[d];
            while (!que.empty()) {
                auto v = que.front();
                que.pop();
                if (disN[v] != d) {
                    continue;
                }
                for (auto[u, w] : adj[v]) {
                    if (chmin(disN[u], disN[v] + w)) {
                        buckets[disN[u]].emplace(u);
                    }
                }
            }
        }
        // dis0[0] = 0;
        // que.emplace(0);
        // while (!que.empty()) {
        //     auto v = que.front();
        //     que.pop();
        //     for (auto u : adj[v]) {
        //         if (dis0[u] == inf) {
        //             dis0[u] = dis0[v] + 1;
        //             que.emplace(u);
        //         }
        //     }
        // }
        // disN[N - 1] = 0;
        // que.emplace(N - 1);
        // while (!que.empty()) {
        //     auto v = que.front();
        //     que.pop();
        //     for (auto u : adj[v]) {
        //         if (disN[u] == inf) {
        //             disN[u] = disN[v] + 1;
        //             que.emplace(u);
        //         }
        //     }
        // }
    }

    std::fill(dis, dis + 2 * N, inf);

    std::vector<int> dis0s(N), disNs(N);
    for (int i = 0; i < N; ++i) {
        dis0s[i] = dis0[roots[i]];
        disNs[i] = disN[roots[i]];
    }
    SparseTable st0(dis0s, std::less());
    SparseTable stN(disNs, std::less());

    for (int i = 0; i < N; ++i) {
        dis[roots[i]] = st0.get(L[i], R[i] + 1)
                      + stN.get(L[i], R[i] + 1)
                      + 1;
        debug(dis[roots[i]]);
        if (dis[roots[i]] < max_N) {
            buckets[dis[roots[i]]].emplace(roots[i]);
        }
    }

    for (int d = 0; d < max_N; ++d) {
        auto& que = buckets[d];
        while (!que.empty()) {
            auto v = que.front();
            que.pop();
            if (dis[v] != d) {
                continue;
            }
            for (auto[u, w] : adj[v]) {
                if (chmin(dis[u], dis[v] + w)) {
                    if (dis[u] < max_N) {
                        buckets[dis[u]].emplace(u);
                    }
                }
            }
        }
    }

    std::cin >> Q;

    for (int i = 0; i < Q; ++i) {
        int X;
        std::cin >> X;
        --X;
        int ans = dis[roots[X]];
        if (ans >= inf) {
            ans = -1;
        }
        std::cout << ans << '\n';
    }

    return 0;
}
#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...