Submission #1011333

#TimeUsernameProblemLanguageResultExecution timeMemory
1011333Muaath_5Werewolf (IOI18_werewolf)C++17
100 / 100
847 ms236968 KiB
#include "werewolf.h" using namespace std; #pragma GCC optimize("Ofast") #include <bits/stdc++.h> #define ll long long #define chmax(x, y) x = max(x, y) #define chmin(x, y) x = min(x, y) #define pii pair<int, int> using namespace std; const int N = 1<<19, INF = 1e9, LG = 20; class reachability { public: int sz; int dsu[N], par[N]; vector<int> adj[N]; reachability(){} reachability(int n) { sz = n; for (int i = 1; i <= n; i++) dsu[i] = par[i] = i; } int root(int x) { return x == dsu[x] ? x : dsu[x] = root(dsu[x]); } bool connect(int u, int v) { u = root(u), v = root(v); if (u == v) return false; sz++; dsu[u] = dsu[v] = dsu[sz] = sz; par[u] = par[v] = par[sz] = sz; adj[sz].push_back(u); adj[sz].push_back(v); return true; } int jmp[N][LG]; int dt[N], ft[N]; int _time; int block[N]; // Maintain minimum/maximum in every subtree int mn[N], mx[N]; void dfsTree() { fill(mx, mx+sz+1, -INF); fill(mn, mn+sz+1, +INF); _time = 1; dfs(sz); } void dfs(int node) { dt[node] = _time++; if (adj[node].size() == 0) mn[node] = mx[node] = node; for (int ch : adj[node]) { dfs(ch); chmin(mn[node], mn[ch]); chmax(mx[node], mx[ch]); } ft[node] = _time-1; } void buildSt() { for (int i = 1; i <= sz; i++) jmp[i][0] = par[i]; for (int j = 1; j < LG; j++) { for (int i = 1; i <= sz; i++) { jmp[i][j] = jmp[jmp[i][j-1]][j-1]; } } } void cutLastEdge() { block[sz] = 1; sz--; } int findCompLeqMx(int u, int lim) { for (int i = LG-1; i >= 0; i--) { if (mx[jmp[u][i]] <= lim) { u = jmp[u][i]; } } return u; } int findCompGeqMn(int u, int lim) { for (int i = LG-1; i >= 0; i--) { if (mn[jmp[u][i]] >= lim) { u = jmp[u][i]; } } return u; } int findComp(int u) { for (int i = LG-1; i >= 0; i--) { if (!block[jmp[u][i]]) { u = jmp[u][i]; } } return u; } }; int tree[4*N]; void update(int idx, int l=0, int r=N-1, int node=1) { if (l == r) { tree[node]++; return; } const int mid = (l+r)/2; if (idx <= mid) update(idx, l, mid, node*2); else update(idx, mid+1, r, node*2+1); tree[node] = tree[node*2] + tree[node*2+1]; } ll query(int ql, int qr, int l=0, int r=N-1, int node=1) { if (ql <= l && r <= qr) return tree[node]; if (l > qr || r < ql) return 0; const int mid = (l+r)/2; return query(ql, qr, l, mid, node*2) + query(ql, qr, mid+1, r, node*2+1); } vector<int> adj[N]; vector<int> check_validity(int N, vector<int> X, vector<int> Y, vector<int> S, vector<int> E, vector<int> L, vector<int> R) { const int M = X.size(), Q = S.size(); for (int i = 0; i < M; i++) X[i]++, Y[i]++; for (int i = 0; i < Q; i++) S[i]++, E[i]++, L[i]++, R[i]++; for (int i = 0; i < M; i++) adj[X[i]].push_back(Y[i]), adj[Y[i]].push_back(X[i]); reachability human(N), werewolf(N); for (int i = 1; i <= N; i++) for (int ch : adj[i]) if (ch <= i) werewolf.connect(i, ch); for (int i = N; i >= 1; i--) for (int ch : adj[i]) if (ch >= i) human.connect(i, ch); human.dfsTree();human.buildSt(); werewolf.dfsTree();werewolf.buildSt(); // [type, yl, yr, idx] const int MX = 1e6; vector<array<int, 4>> evts[MX]; for (int i = 1; i <= N; i++) evts[human.dt[i]].push_back({0, werewolf.dt[i], 0, 0}); for (int i = 0; i < Q; i++) { int u = human.findCompGeqMn(S[i], L[i]); // [L...N] int v = werewolf.findCompLeqMx(E[i], R[i]); // [1...R] evts[human.dt[u]-1].push_back({-1, werewolf.dt[v], werewolf.ft[v], i}); evts[human.ft[u]].push_back({1, werewolf.dt[v], werewolf.ft[v], i}); } vector<int> sol(Q); for (int i = 0; i < MX; i++) { for (auto [type,a,b,idx] : evts[i]) { if (type == 0) { update(a); } else { //cerr << i << ' ' << a << ' ' << b << endl; sol[idx] += type * query(a, b); } } } for (int i = 0; i < Q; i++) sol[i] = !!sol[i]; return sol; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...