Submission #394735

#TimeUsernameProblemLanguageResultExecution timeMemory
394735KoDJoker (BOI20_joker)C++17
100 / 100
1064 ms27380 KiB
#include <bits/stdc++.h>

using i32 = std::int32_t;
using u32 = std::uint32_t;
using i64 = std::int64_t;
using u64 = std::uint64_t;
using i128 = __int128_t;
using u128 = __uint128_t;
using isize = std::ptrdiff_t;
using usize = std::size_t;

class rep {
    struct Iter {
        usize itr;
        constexpr Iter(const usize pos) noexcept : itr(pos) {}
        constexpr void operator++() noexcept { ++itr; }
        constexpr bool operator!=(const Iter& other) const noexcept {
            return itr != other.itr;
        }
        constexpr usize operator*() const noexcept { return itr; }
    };
    const Iter first, last;

  public:
    explicit constexpr rep(const usize first, const usize last) noexcept
        : first(first), last(std::max(first, last)) {}
    constexpr Iter begin() const noexcept { return first; }
    constexpr Iter end() const noexcept { return last; }
};

template <class F> struct RecLambda : private F {
    template <class G>
    explicit constexpr RecLambda(G&& g) : F(std::forward<G>(g)) {}
    template <class... Args>
    constexpr decltype(auto) operator()(Args&&... args) const {
        return F::operator()(*this, std::forward<Args>(args)...);
    }
};

template <class G> explicit RecLambda(G&&) -> RecLambda<std::decay_t<G>>;

class UnionFindRollback {
    std::vector<usize> data;
    std::stack<std::pair<usize, usize>> history;

  public:
    explicit UnionFindRollback(const usize size = 0)
        : data(size, -1), history() {}

    usize size() const { return data.size(); }

    usize leader(usize u) const {
        assert(u < size());
        while (data[u] < size()) u = data[u];
        return u;
    }

    usize size(const usize u) const {
        assert(u < size());
        return -data[leader(u)];
    }

    std::pair<usize, bool> merge(usize u, usize v) {
        assert(u < size());
        assert(v < size());
        u = leader(u);
        v = leader(v);
        if (u == v) return std::make_pair(u, false);
        if (data[u] > data[v]) std::swap(u, v);
        history.emplace(u, data[u]);
        history.emplace(v, data[v]);
        data[u] += data[v];
        data[v] = u;
        return std::make_pair(u, true);
    }

    bool same(const usize u, const usize v) const {
        assert(u < size());
        assert(v < size());
        return leader(u) == leader(v);
    }

    void rollback(const usize steps) {
        assert(2 * steps <= history.size());
        for (usize i = 2 * steps; i > 0; --i) {
            const auto [k, x] = history.top();
            history.pop();
            data[k] = x;
        }
    }
};

template <class T> using Vec = std::vector<T>;

void BOI20_joker_main() {
    usize N, M, Q;
    std::cin >> N >> M >> Q;
    Vec<usize> A(M), B(M);
    for (const auto i : rep(0, M)) {
        std::cin >> A[i] >> B[i];
        A[i] -= 1;
        B[i] -= 1;
    }
    Vec<usize> last(M);
    UnionFindRollback dsu(2 * N);
    Vec<bool> bip;
    bip.push_back(true);
    const auto add_edge = [&](const usize e) {
        if (dsu.merge(A[e], B[e] + N).second) {
            bip.push_back(bip.back() and !dsu.same(A[e], A[e] + N) and
                          !dsu.same(B[e], B[e] + N));
        }
        if (dsu.merge(A[e] + N, B[e]).second) {
            bip.push_back(bip.back() and !dsu.same(A[e], A[e] + N) and
                          !dsu.same(B[e], B[e] + N));
        }
    };
    const auto back_until = [&](const usize time) {
        dsu.rollback(bip.size() - time);
        bip.resize(time);
    };
    RecLambda([&](auto&& dfs, const usize il, const usize ir, const usize jl,
                  const usize jr) -> void {
        if (!bip.back()) {
            std::fill(last.begin() + il, last.begin() + ir + 1, jr);
            return;
        }
        const auto im = (il + ir) / 2;
        {
            const auto time = bip.size();
            for (const auto i : rep(il, im)) {
                add_edge(i);
            }
            last[im] = jr;
            while (bip.back() and last[im] > im) {
                last[im] -= 1;
                add_edge(last[im]);
            }
            back_until(time);
        }
        if (il < im) {
            const auto time = bip.size();
            for (const auto i : rep(last[im], jr)) {
                add_edge(i);
            }
            dfs(il, im - 1, jl, last[im]);
            back_until(time);
        }
        if (im < ir) {
            const auto time = bip.size();
            for (const auto i : rep(il, im + 1)) {
                add_edge(i);
            }
            dfs(im + 1, ir, last[im], jr);
            back_until(time);
        }
    })(0, M - 1, 0, M);
    while (Q--) {
        usize l, r;
        std::cin >> l >> r;
        l -= 1;
        std::cout << (r <= last[l] ? "YES" : "NO") << '\n';
    }
}

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);
    BOI20_joker_main();
    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...
#Verdict Execution timeMemoryGrader output
Fetching results...