제출 #1324260

#제출 시각아이디문제언어결과실행 시간메모리
1324260duckindogRailway Trip 2 (JOI22_ho_t4)C++20
100 / 100
999 ms46108 KiB
#include <bits/stdc++.h>

using namespace std;

const int N = 200'000 + 10;
int n, k;
int m, q;
struct Train { 
    int st, ed;
    friend istream& operator >> (istream& is, Train& rhs) { 
        return is >> rhs.st >> rhs.ed;
    }
} train[N];

struct IT { 
    using pii = pair<int, int>;
    pii f[N << 2];

    pii merge(const pii& lt, const pii& rt) { 
        return {min(lt.first, rt.first), max(lt.second, rt.second)};
    }

    void build(int u, int l, int r) { 
        if (l == r) { 
            f[u] = {l, l};
            return;
        }
        int mid = (l + r) >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
        f[u] = merge(f[u << 1], f[u << 1 | 1]);
    }
    void update(int u, int l, int r, int pos, pii val) { 
        if (l == r) { 
            f[u] = merge(f[u], val);
            return;
        }
        int mid = (l + r) >> 1;
        if (pos <= mid) update(u << 1, l, mid, pos, val);
        else update(u << 1 | 1, mid + 1, r, pos, val);
        f[u] = merge(f[u << 1], f[u << 1 | 1]);
    }
    pii query(int u, int l, int r, int ql, int qr) { 
        if (ql <= l && r <= qr) return f[u];
        int mid = (l + r) >> 1;
        pii res = {n + 1, 0};
        if (ql <= mid) res = merge(res, query(u << 1, l, mid, ql, qr));
        if (qr > mid) res = merge(res, query(u << 1 | 1, mid + 1, r, ql, qr));
        return res;
    }
} T[18];

int32_t main() { 
    cin.tie(0)->sync_with_stdio(0);

    cin >> n >> k;
    cin >> m;
    for (int i = 1; i <= m; ++i) cin >> train[i];

    { // cal f[][0]
        vector<tuple<int, int, int>> vt;
        for (int i = 1; i <= m; ++i) { 
            const auto& [st, ed] = train[i];

            if (st < ed) { 
                int p = min(ed - 1, st + k - 1);
                vt.emplace_back(ed, st, p);
            } else { 
                int p = max(ed + 1, st - k + 1);
                vt.emplace_back(ed, p, st);
            }
        }

        for (int j = 0; j < 18; ++j) T[j].build(1, 1, n);
        for (int turn = 0; turn < 2; ++turn) { 
            if (!turn) sort(vt.begin(), vt.end());
            else sort(vt.begin(), vt.end(), greater<>());

            set<int> s;
            for (int i = 1; i <= n; ++i) s.insert(i);

            for (const auto& [value, l, r] : vt) { 
                auto it = s.lower_bound(l);
                while (it != s.end() && *it <= r) { 
                    int i = *it;
                    T[0].update(1, 1, n, i, {value, value});
                    it = s.erase(it);
                }
            }
        }
    }
    { // cal f[i] for sparse table
        for (int j = 1; j < 18; ++j) { 
            for (int i = 1; i <= n; ++i) { 
                auto [l, r] = T[j - 1].query(1, 1, n, i, i);
                T[j].update(1, 1, n, i, T[j - 1].query(1, 1, n, l, r));
            }
        }
    }

    cin >> q;
    while (q--) { 
        int st, ed; cin >> st >> ed;

        if (st == ed) { 
            cout << 0 << "\n";
            continue;
        }

        int answer = 0;
        int l = st, r = st;
        for (int j = 17; j >= 0; --j) { 
            auto [lt, rt] = T[j].query(1, 1, n, l, r);
            if (lt <= ed && ed <= rt) continue;

            l = lt;
            r = rt;
            answer |= (1 << j);
        }

        { // check if can reach ed
            auto [lt, rt] = T[0].query(1, 1, n, l, r);
            if (lt <= ed && ed <= rt) answer += 1;
            else answer = -1;
        }

        cout << answer << '\n';
    }
}
#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...