Submission #768690

#TimeUsernameProblemLanguageResultExecution timeMemory
768690jakobrsJoker (BOI20_joker)C++17
100 / 100
1625 ms10908 KiB
#pragma GCC optimize("O3") #include <algorithm> #include <iostream> #include <vector> using i64 = int64_t; using i32 = int32_t; struct Operation { i32 l1, r1; }; constexpr i64 root(i64 n) { i64 i = 0; for (; i * i <= n; i++) ; return i - 1; } class UnionFind { std::vector<i32> parent; std::vector<i32> sizes; std::vector<bool> edge_parity; std::vector<Operation> operations; public: UnionFind(size_t sz) : parent(sz, -1), sizes(sz, 1), edge_parity(sz, false), operations() {} template <bool PATH_COMPRESSION> i32 find(i32 idx) { if (parent[idx] < 0) return idx; else if constexpr (PATH_COMPRESSION) { i64 root = find<PATH_COMPRESSION>(parent[idx]); edge_parity[idx] = edge_parity[idx] ^ edge_parity[parent[idx]]; return parent[idx] = root; } else return find<PATH_COMPRESSION>(parent[idx]); } bool parity(i32 idx) { if (parent[idx] < 0) return false; else return parity(parent[idx]) ^ edge_parity[idx]; } template <bool PATH_COMPRESSION> std::pair<i32, bool> both(i32 idx) { if constexpr (PATH_COMPRESSION) { return {find<true>(idx), parity(idx)}; } else { // in this case there's an easy iterative version bool parity = false; while (parent[idx] >= 0) { parity = parity ^ edge_parity[idx]; idx = parent[idx]; } return {idx, parity}; } } template <bool PATH_COMPRESSION> bool lag_fagforening(i32 l, i32 r) { auto [l1, lp] = both<PATH_COMPRESSION>(l); auto [r1, rp] = both<PATH_COMPRESSION>(r); operations.push_back({ .l1 = l1, .r1 = r1, }); if (l1 == r1) { return lp != rp; } else { if (sizes[l1] < sizes[r1]) { std::swap(l1, r1); std::swap(lp, rp); } sizes[l1] += sizes[r1]; parent[r1] = l1; edge_parity[r1] = 1 ^ lp ^ rp; return true; } } void tvungen_lønnsnemnd() { auto [l1, r1] = operations.back(); operations.pop_back(); if (parent[r1] == l1) { parent[r1] = -1; sizes[l1] -= sizes[r1]; } else if (parent[l1] == r1) { parent[l1] = -1; sizes[r1] -= sizes[l1]; } edge_parity[l1] = edge_parity[r1] = false; } }; struct { template <typename T> operator T() const { T x; std::cin >> x; return x; } } in; #define entire(v) std::begin(v), std::end(v) #pragma GCC diagnostic ignored "-Wreturn-type" main() { std::cin.tie(nullptr)->sync_with_stdio(false); i32 n, m, q; std::cin >> n >> m >> q; std::vector<std::pair<i32, i32>> edges(m); for (i32 i = 0; i < m; i++) { edges[i] = {(i32)in - 1, (i32)in - 1}; } UnionFind dsu(n); static constexpr i32 root_m = 1024; struct Query { i32 l, r, i; }; std::vector<Query> queries(q); for (i32 i = 0; i < q; i++) queries[i] = {(i32)in - 1, (i32)in, i}; std::sort(entire(queries), [](auto &&lhs, auto &&rhs) { return std::pair<i32, i32>{lhs.l / root_m, -lhs.r} < std::pair<i32, i32>{rhs.l / root_m, -rhs.r}; }); std::vector<bool> answers(q); i32 l = 0; i32 r = 0; bool is_bipartite_left = true; for (i32 start = 0; start < m && is_bipartite_left; start += root_m) { while (r < q && queries[r].l < start + root_m) r++; bool is_bipartite_right = true; i32 w = m; for (; l < r && is_bipartite_right; l++) { for (; w > queries[l].r && is_bipartite_right; w--) is_bipartite_right &= dsu.lag_fagforening<false>(edges[w - 1].first, edges[w - 1].second); if (!is_bipartite_right) break; bool is_bipartite = true; i32 g = start; for (; g < queries[l].l && is_bipartite; g++) is_bipartite &= dsu.lag_fagforening<false>(edges[g].first, edges[g].second); answers[queries[l].i] = is_bipartite; for (i32 u = start; u < g; u++) dsu.tvungen_lønnsnemnd(); } for (; l < r; l++) answers[queries[l].i] = false; for (i32 x = w; x < m; x++) dsu.tvungen_lønnsnemnd(); for (i32 y = start; y < start + root_m && y < m; y++) is_bipartite_left &= dsu.lag_fagforening<true>(edges[y].first, edges[y].second); } for (; l < q; l++) answers[queries[l].i] = false; for (auto x : answers) { std::cout << (x ? "NO\n" : "YES\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...