Submission #522571

#TimeUsernameProblemLanguageResultExecution timeMemory
522571CyanmondSwapping Cities (APIO20_swap)C++17
100 / 100
671 ms43760 KiB
#line 1 "paper.cpp" #include <bits/stdc++.h> #line 3 "library2/utility/int_alias.hpp" using i8 = std::int8_t; using u8 = std::uint8_t; using i16 = std::int16_t; using i32 = std::int32_t; using i64 = std::int64_t; using u16 = std::uint16_t; using u32 = std::uint32_t; using u64 = std::uint64_t; #line 3 "library2/utility/len.hpp" template <class Container> int len(const Container&c){ return static_cast<int>(std::size(c)); } #line 6 "library2/utility/priority_sort.hpp" namespace magic { template <class T, class... Tail> void priority_sort_renumber(const std::vector<int> &order, std::vector<T> &head, Tail &...tail) { const int n = len(order); std::vector<T> sorted_head(n); for (int i = 0; i < n; ++i) { sorted_head[i] = head[order[i]]; } head = std::move(sorted_head); if constexpr (sizeof...(Tail) != 0) { priority_sort_renumber(order, tail...); } } } // namespace magic template <class Head, class... Tail> std::vector<int> priority_sort(std::vector<Head> &head, std::vector<Tail> &...tail) { const int n = len(head); std::vector<std::tuple<Head, Tail..., int>> res(n); for (int i = 0; i < n; ++i) { res[i] = std::make_tuple(head[i], tail[i]..., i); } std::sort(res.begin(), res.end()); std::vector<int> order(n); for (int i = 0; i < n; ++i) { order[i] = std::get<std::tuple_size_v<std::tuple<Head, Tail...>>>(res[i]); } magic::priority_sort_renumber(order, head, tail...); return order; } #line 3 "library2/utility/rep.hpp" class Range { struct Iterator { int itr; constexpr Iterator(const int pos) noexcept : itr(pos) {} constexpr void operator++() noexcept { ++itr; } constexpr bool operator!=(const Iterator &other) const noexcept { return itr != other.itr; } constexpr int operator*() const noexcept { return itr; } }; const Iterator first, last; public: explicit constexpr Range(const int f, const int l) noexcept : first(f), last(std::max(f, l)) {} constexpr Iterator begin() const noexcept { return first; } constexpr Iterator end() const noexcept { return last; } }; constexpr Range rep(const int l, const int r) noexcept { return Range(l, r); } constexpr Range rep(const int n) noexcept { return Range(0, n); } #line 6 "paper.cpp" class BubunEizokuUnionFindKaizou { int n; struct Node { int parent; int size; int deg1; int deg2; int deg3; bool cycle; }; std::vector<Node> now_data; std::vector<i64> last_time; std::vector<std::vector<std::pair<i64, Node>>> history; std::vector<int> degree; std::vector<std::vector<std::pair<i64, int>>> deg_history; public: BubunEizokuUnionFindKaizou() = default; BubunEizokuUnionFindKaizou(const int n_) : n(n_) { now_data.resize(n); history.resize(n); for (const int i : rep(n)) { now_data[i] = {i, 1, 0, 0}; history[i].push_back({0, {i, 1, 0, 0, 0, false}}); } degree.assign(n, 0); last_time.assign(n, -1); deg_history.resize(n); for (const int i : rep(n)) { deg_history[i].push_back({0, 0}); } } bool same(int a, int b, i64 t) { return root(a, t) == root(b, t); } int root(int v, i64 t) { if (last_time[v] == -1 or t < last_time[v]) { return v; } else { return root(now_data[v].parent, t); } } void unite(int a, int b, i64 c) { int ra = root(a, c), rb = root(b, c); if (ra == rb) { now_data[ra].cycle = true; if (degree[a] <= 3) { if (degree[a] == 0) { ++now_data[ra].deg1; } if (degree[a] == 1) { --now_data[ra].deg1; ++now_data[ra].deg2; } if (degree[a] == 2) { --now_data[ra].deg2; ++now_data[ra].deg3; } if (degree[a] == 3) { --now_data[ra].deg3; } } if (degree[b] <= 3) { if (degree[b] == 0) { ++now_data[ra].deg1; } if (degree[b] == 1) { --now_data[ra].deg1; ++now_data[ra].deg2; } if (degree[b] == 2) { --now_data[ra].deg2; ++now_data[ra].deg3; } } ++degree[a]; ++degree[b]; history[ra].push_back({c, now_data[ra]}); } else { if (now_data[ra].size < now_data[rb].size) { std::swap(a, b); std::swap(ra, rb); } now_data[ra].size += now_data[rb].size; now_data[rb].parent = ra; now_data[ra].deg1 += now_data[rb].deg1; now_data[ra].deg2 += now_data[rb].deg2; now_data[ra].deg3 += now_data[rb].deg3; now_data[ra].cycle |= now_data[rb].cycle; last_time[rb] = c; if (degree[a] <= 2) { if (degree[a] == 0) { ++now_data[ra].deg1; } if (degree[a] == 1) { --now_data[ra].deg1; ++now_data[ra].deg2; } if (degree[a] == 2) { --now_data[ra].deg2; ++now_data[ra].deg3; } } if (degree[b] <= 2) { if (degree[b] == 0) { ++now_data[ra].deg1; } if (degree[b] == 1) { --now_data[ra].deg1; ++now_data[ra].deg2; } if (degree[b] == 2) { --now_data[ra].deg2; ++now_data[ra].deg3; } } ++degree[a]; ++degree[b]; deg_history[a].push_back({c, degree[a]}); deg_history[b].push_back({c, degree[b]}); history[ra].push_back({c, now_data[ra]}); } } int deg(int v, i64 t) { return (--std::upper_bound(deg_history[v].begin(), deg_history[v].end(), std::make_pair(t, 1000000001))) ->second; } Node view(int v, i64 t) { v = root(v, t); return (--std::upper_bound(history[v].begin(), history[v].end(), std::make_pair(t, 0), [](auto a, auto b) { return a.first < b.first; })) ->second; } }; int N, M; std::vector<int> U, V, W; BubunEizokuUnionFindKaizou uft; void init(int n, int m, std::vector<int> u, std::vector<int> v, std::vector<int> w) { N = n; M = m; U = u; V = v; W = w; uft = BubunEizokuUnionFindKaizou(N); priority_sort(W, U, V); for (const int i : rep(M)) { uft.unite(U[i], V[i], W[i]); } } int getMinimumFuelCapacity(int X, int Y) { if (not uft.same(X, Y, 1000000001)) { return -1; } const auto bestnode = uft.view(X, 1000000001); if ((not bestnode.cycle) and (bestnode.deg3 == 0)) { return -1; } int ok = 1000000001, ng = -1; while (ok - ng > 1) { const auto mid = (ok + ng) / 2; if (not uft.same(X, Y, mid)) { ng = mid; } else { const auto node = uft.view(X, mid); if ((not node.cycle) and (node.deg3 == 0)) { ng = mid; } else { ok = mid; } } } return ok; } /* int main() { int N, M; assert(2 == scanf("%d %d", &N, &M)); std::vector<int> U(M), V(M), W(M); for (int i = 0; i < M; ++i) { assert(3 == scanf("%d %d %d", &U[i], &V[i], &W[i])); } int Q; assert(1 == scanf("%d", &Q)); std::vector<int> X(Q), Y(Q); for (int i = 0; i < Q; ++i) { assert(2 == scanf("%d %d", &X[i], &Y[i])); } init(N, M, U, V, W); std::vector<int> minimum_fuel_capacities(Q); for (int i = 0; i < Q; ++i) { minimum_fuel_capacities[i] = getMinimumFuelCapacity(X[i], Y[i]); } for (int i = 0; i < Q; ++i) { printf("%d\n", minimum_fuel_capacities[i]); } 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...