Submission #108163

#TimeUsernameProblemLanguageResultExecution timeMemory
108163Noam527Werewolf (IOI18_werewolf)C++17
100 / 100
2366 ms123432 KiB
#include <bits/stdc++.h> #define CHECK cout << "ok" << endl #define finish(x) return cout << x << endl, 0 typedef long long ll; typedef long double ldb; const int md = 1e9 + 7; const ll inf = 1e18; const int OO = 0; const int OOO = 1; using namespace std; const int mxn = 2e5 + 5; int n; vector<int> g[mxn]; int num[mxn]; int denum[mxn]; int good[mxn]; int root[mxn], sz[mxn]; vector<int> compv[mxn]; vector<vector<int>> ranges[mxn]; vector<pair<int, int>> roots[mxn]; set<int> comps[mxn]; vector<int> add(int v) { good[v] = 1; vector<int> rtn; for (const auto &i : g[v]) if (good[i]) rtn.push_back(i); return rtn; } void numerate() { vector<int> a; for (int i = 0; i < n; i++) { num[i] = good[i] = 0; sz[i] = 1; root[i] = i; compv[i].push_back(i); } for (int i = n - 1; i >= 0; i--) { a = add(i); for (const auto &v : a) { // connect v, i int x = root[i], y = root[v]; if (x == y) continue; if (sz[x] > sz[y]) swap(x, y); for (const auto &u : compv[x]) { root[u] = y; num[u] += sz[y]; compv[y].push_back(u); } sz[y] += sz[x]; compv[x].clear(); } } for (int i = 0; i < n; i++) denum[num[i]] = i; for (int i = 0; i < n; i++) compv[i].clear(); // numerated. now ranges for (int i = 0; i < n; i++) { good[i] = 0; sz[i] = 1; root[i] = i; compv[i].push_back(i); ranges[i].push_back({ n, num[i], num[i] }); roots[i].emplace_back(n, i); } for (int i = n - 1; i >= 0; i--) { a = add(i); for (const auto &v : a) { int x = root[i], y = root[v]; if (x == y) continue; if (sz[x] > sz[y]) swap(x, y); for (const auto &u : compv[x]) { root[u] = y; compv[y].push_back(u); roots[u].emplace_back(i, y); } sz[y] += sz[x]; compv[x].clear(); ranges[y].push_back({ i, min(ranges[x].back()[1], ranges[y].back()[1]), max(ranges[x].back()[2], ranges[y].back()[2]) }); } } } pair<int, int> getrange(int time, int v) { int lo, hi, mid; lo = 0, hi = (int)roots[v].size() - 1; while (lo < hi) { mid = (lo + hi + 1) / 2; if (roots[v][mid].first >= time) lo = mid; else hi = mid - 1; } v = roots[v][lo].second; lo = 0, hi = (int)ranges[v].size() - 1; while (lo < hi) { mid = (lo + hi + 1) / 2; if (ranges[v][mid][0] >= time) lo = mid; else hi = mid - 1; } return{ ranges[v][lo][1], ranges[v][lo][2] }; } struct query { int l, r, s, e, ind; query() {} query(int ll, int rr, int ss, int ee, int ii) : l(ll), r(rr), s(ss), e(ee), ind(ii) {} bool operator < (const query &a) const { return r < a.r; } }; vector<int> check_validity(int N, vector<int> X, vector<int> Y, vector<int> S, vector<int> E, vector<int> L, vector<int> R) { n = N; for (int i = 0; i < X.size(); i++) { g[X[i]].push_back(Y[i]); g[Y[i]].push_back(X[i]); } numerate(); if (OO) { /* cout << "numerated: "; for (int i = 0; i < n; i++) cout << num[i] << " "; cout << '\n'; while (1) { cout << "L, v: "; int tim, v; cin >> tim >> v; pair<int, int> tmp = getrange(tim, v); cout << "[" << tmp.first << ", " << tmp.second << "]\n"; } */ } for (int i = 0; i < n; i++) { good[i] = 0; sz[i] = 1; root[i] = i; comps[i].insert(num[i]); } vector<int> a; int q = S.size(); vector<int> ans(q); vector<query> Q(q); for (int i = 0; i < q; i++) Q[i] = query(L[i], R[i], S[i], E[i], i); sort(Q.begin(), Q.end()); int nxt = 0; for (const auto &i : Q) { if (OO) { cout << "processing query:\n"; cout << "(S, E, L, R) = " << i.s << " " << i.e << " " << i.l << " " << i.r << '\n'; } while (nxt <= i.r) { a = add(nxt); if (OO) { cout << nxt << " becomes good: "; for (const auto &j : a) cout << j << " "; cout << '\n'; } for (const auto &v : a) { int x = root[nxt], y = root[v]; if (OO) cout << "merging " << nxt << " " << v << " = " << x << " " << y << '\n'; if (x == y) continue; if (sz[x] > sz[y]) swap(x, y); for (const auto &u : comps[x]) { root[denum[u]] = y; comps[y].insert(u); } sz[y] += sz[x]; comps[x].clear(); } nxt++; } if (OO) { cout << "roots: "; for (int j = 0; j < n; j++) cout << root[j] << " "; cout << '\n'; } pair<int, int> tmp = getrange(i.l, i.s); auto it = comps[root[i.e]].lower_bound(tmp.first); if (it == comps[root[i.e]].end() || tmp.second < *it) ans[i.ind] = 0; else ans[i.ind] = 1; } return ans; }

Compilation message (stderr)

werewolf.cpp: In function 'std::vector<int> check_validity(int, std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>)':
werewolf.cpp:123:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < X.size(); i++) {
                  ~~^~~~~~~~~~
werewolf.cpp:167:5: warning: this 'for' clause does not guard... [-Wmisleading-indentation]
     for (const auto &j : a) cout << j << " "; cout << '\n';
     ^~~
werewolf.cpp:167:47: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'for'
     for (const auto &j : a) cout << j << " "; cout << '\n';
                                               ^~~~
werewolf.cpp:185:4: warning: this 'for' clause does not guard... [-Wmisleading-indentation]
    for (int j = 0; j < n; j++) cout << root[j] << " "; cout << '\n';
    ^~~
werewolf.cpp:185:56: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'for'
    for (int j = 0; j < n; j++) cout << root[j] << " "; cout << '\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...