Submission #676037

#TimeUsernameProblemLanguageResultExecution timeMemory
676037HegdahlWerewolf (IOI18_werewolf)C++17
100 / 100
981 ms163412 KiB
#include "werewolf.h" #include <bits/stdc++.h> using namespace std; template <class F> struct yc { F f_; yc(F &&f) : f_(std::forward<F>(f)) {} decltype(auto) operator()(auto &&...args) { return f_(std::ref(*this), std::forward<decltype(args)>(args)...); } }; struct krusk { vector<array<int, 18>> u; vector<int> l, r, lo, hi; vector<int> order, where; vector<int> lm, rm; krusk(int n, const vector<array<int, 2>> &e) : u(2 * n - 1), l(n - 1, -1), r(n - 1, -1), lo(2 * n - 1), hi(2 * n - 1), where(2 * n - 1, -1), lm(2 * n - 1, (int)1e9), rm(2 * n - 1, -(int)1e9) { vector<int> boss(n, -1), root(n); iota(root.begin(), root.end(), 0); iota(lo.begin(), lo.begin() + n, 0); iota(hi.begin(), hi.begin() + n, 0); int nxt = n; auto find = yc([&](auto find, int i) -> int { if (boss[i] < 0) return i; return boss[i] = find(boss[i]); }); auto unite = [&](int i, int j) { i = find(i), j = find(j); if (i == j) return false; if (boss[i] > boss[j]) swap(i, j); boss[i] += boss[j]; boss[j] = i; l[nxt - n] = root[i]; r[nxt - n] = root[j]; lo[nxt] = min(lo[root[i]], lo[root[j]]); hi[nxt] = max(hi[root[i]], hi[root[j]]); root[i] = nxt; root[j] = -1; ++nxt; return true; }; for (auto [i, j] : e) unite(i, j); assert(nxt == 2 * n - 1); order.reserve(2 * n - 1); auto dfs = yc([&](auto dfs, int i, int p) -> void { u[i][0] = p; for (int lvl = 0; lvl + 1 < u[i].size(); ++lvl) u[i][lvl + 1] = u[u[i][lvl]][lvl]; if (i >= n && l[i - n] >= 0) dfs(l[i - n], i); where[i] = (int)order.size(); order.push_back(i); lm[i] = min(lm[i], where[i]); rm[i] = max(rm[i], where[i]); if (i >= n && r[i - n] >= 0) dfs(r[i - n], i); lm[p] = min(lm[p], lm[i]); rm[p] = max(rm[p], rm[i]); }); dfs(nxt - 1, nxt - 1); } array<int, 2> qry(int i, int mn, int mx) { assert(mn <= lo[i] && hi[i] <= mx); for (int lvl = (int)u[i].size() - 1; lvl >= 0; --lvl) { int j = u[i][lvl]; if (mn <= lo[j] && hi[j] <= mx) i = j; } return {lm[i], rm[i]}; } }; vector<int> check_validity(int n, vector<int> ei, vector<int> ej, vector<int> starts, vector<int> targets, vector<int> los, vector<int> his) { int m = (int)ei.size(); assert((int)ej.size() == m); vector<array<int, 2>> e(m); for (int mm = 0; mm < m; ++mm) { auto &[i, j] = e[mm]; i = ei[mm]; j = ej[mm]; } sort(e.begin(), e.end(), [&](auto e0, auto e1) { auto [i0, j0] = e0; auto [i1, j1] = e1; return max(i0, j0) < max(i1, j1); }); auto lo_tree = krusk(n, e); sort(e.begin(), e.end(), [&](auto e0, auto e1) { auto [i0, j0] = e0; auto [i1, j1] = e1; return min(i0, j0) > min(i1, j1); }); auto hi_tree = krusk(n, e); int q = (int)starts.size(); assert(q == (int)targets.size()); assert(q == (int)los.size()); assert(q == (int)his.size()); vector<int> ans(q); int offset = 1; while (offset < 2 * n - 1) offset *= 2; vector<basic_string<int>> st(2 * offset); for (int i = 0; i < n; ++i) st[offset + hi_tree.where[i]].push_back(lo_tree.where[i]); for (int I = offset - 1; I; --I) std::merge(st[2 * I].begin(), st[2 * I].end(), st[2 * I + 1].begin(), st[2 * I + 1].end(), back_inserter(st[I])); auto check = [&](const auto &v, int lo, int hi) { auto it0 = lower_bound(v.begin(), v.end(), lo); auto it1 = upper_bound(v.begin(), v.end(), hi); return it0 != it1; }; auto qry = [&](int i, int j, int x, int y) { i += offset - 1; j += offset + 1; while (i + 1 < j) { if (i % 2 == 0 && check(st[i + 1], x, y)) return true; if (j % 2 == 1 && check(st[j - 1], x, y)) return true; i >>= 1, j >>= 1; } return false; }; for (int qq = 0; qq < q; ++qq) { int s = starts[qq]; int t = targets[qq]; int lo = los[qq]; int hi = his[qq]; auto [sl, sr] = hi_tree.qry(s, lo, n - 1); auto [tl, tr] = lo_tree.qry(t, 0, hi); ans[qq] = qry(sl, sr, tl, tr); } return ans; }

Compilation message (stderr)

werewolf.cpp:11:29: warning: use of 'auto' in parameter declaration only available with '-fconcepts-ts'
   11 |   decltype(auto) operator()(auto &&...args) {
      |                             ^~~~
werewolf.cpp: In instantiation of 'krusk::krusk(int, const std::vector<std::array<int, 2> >&)::<lambda(auto:25, int, int)> [with auto:25 = std::reference_wrapper<yc<krusk::krusk(int, const std::vector<std::array<int, 2> >&)::<lambda(auto:25, int, int)> > >]':
werewolf.cpp:12:14:   required from 'decltype(auto) yc<F>::operator()(auto:23&& ...) [with auto:23 = {int, int}; F = krusk::krusk(int, const std::vector<std::array<int, 2> >&)::<lambda(auto:25, int, int)>]'
werewolf.cpp:82:25:   required from here
werewolf.cpp:68:33: warning: comparison of integer expressions of different signedness: 'int' and 'std::array<int, 18>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   68 |       for (int lvl = 0; lvl + 1 < u[i].size(); ++lvl)
      |                         ~~~~~~~~^~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...