제출 #1010469

#제출 시각아이디문제언어결과실행 시간메모리
1010469Muaath_5Werewolf (IOI18_werewolf)C++17
15 / 100
1378 ms524288 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; } }; #define OUT 0ll int merge(int x, int y) { return x + y; } static int R = 1 << 19, C = 1 << 19; struct ynode { int val = OUT; ynode *left = nullptr, *right = nullptr; }; struct xnode { xnode *left, *right; ynode *yy; }; ll query_y(const int& qy1, const int& qy2, ynode* node, int l = 0, int r = C - 1) { if (node == nullptr || r < qy1 || qy2 < l) return OUT; if (qy1 <= l && r <= qy2) return node->val; const int mid = (l + r) / 2; return merge( query_y(qy1, qy2, node->left, l, mid), query_y(qy1, qy2, node->right, mid + 1, r) ); } ll query_x(const int& qx1, const int& qy1, const int& qx2, const int& qy2, xnode* node, int l = 0, int r = R - 1) { if (node == nullptr || r < qx1 || qx2 < l) return OUT; if (qx1 <= l && r <= qx2) return query_y(qy1, qy2, node->yy); const int mid = (l + r) / 2; return merge( query_x(qx1, qy1, qx2, qy2, node->left, l, mid), query_x(qx1, qy1, qx2, qy2, node->right, mid + 1, r) ); } void update_y(const int& qy, const int& val, ynode* node, int l = 0, int r = C - 1) { if (l == r) { node->val = val; return; } const int mid = (l + r) / 2; if (qy <= mid) { if (!node->left) node->left = new ynode(); update_y(qy, val, node->left, l, mid); } else { if (!node->right) node->right = new ynode(); update_y(qy, val, node->right, mid + 1, r); } ll m1 = OUT, m2 = OUT; if (node->left) m1 = node->left->val; if (node->right) m2 = node->right->val; node->val = merge(m1, m2); } void update_x(const int& qx, const int& qy, const ll& val, xnode* node, int l = 0, int r = R - 1) { if (!node->yy) node->yy = new ynode(); if (l == r) { update_y(qy, val, node->yy); return; } const int mid = (l + r) / 2; if (qx <= mid) { if (!node->left) node->left = new xnode(); update_x(qx, qy, val, node->left, l, mid); } else { if (!node->right) node->right = new xnode(); update_x(qx, qy, val, node->right, mid + 1, r); } update_y(qy, merge( (node->left && node->left->yy ? query_y(qy, qy, node->left->yy) : OUT), (node->right && node->right->yy ? query_y(qy, qy, node->right->yy) : OUT) ), node->yy); } xnode* root; void init(int r, int c) { R = r, C = c, root = new xnode(); } void update(int x, int y, int k) { update_x(x, y, k, root); } int query(int x1, int y1, int x2, int y2) { return query_x(x1, y1, x2, y2, root); } 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(); init(human.sz+1, werewolf.sz+1); for (int i = 1; i <= N; i++) { update(human.dt[i], werewolf.dt[i], 1); } vector<int> sol(Q); 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] sol[i] = !!query(human.dt[u], werewolf.dt[v], human.ft[u], werewolf.ft[v]); } 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...