제출 #1196408

#제출 시각아이디문제언어결과실행 시간메모리
1196408icebearWerewolf (IOI18_werewolf)C++20
0 / 100
584 ms162216 KiB
// ~~ icebear love attttt ~~ #include <bits/stdc++.h> #include "werewolf.h" using namespace std; typedef long long ll; typedef pair<int, int> ii; typedef pair<int, ii> iii; template<class T> bool minimize(T &a, const T &b) { if (a > b) return a = b, true; return false; } template<class T> bool maximize(T &a, const T &b) { if (a < b) return a = b, true; return false; } #define FOR(i,a,b) for(int i=(a); i<=(b); ++i) #define FORR(i,a,b) for(int i=(a); i>=(b); --i) #define REP(i, n) for(int i=0; i<(n); ++i) #define RED(i, n) for(int i=(n)-1; i>=0; --i) #define MASK(i) (1LL << (i)) #define BIT(S, i) (((S) >> (i)) & 1) #define mp make_pair #define pb push_back #define fi first #define se second #define all(x) x.begin(), x.end() #define task "icebearat" const int MOD = 1e9 + 7; const int inf = 1e9 + 27092008; const ll INF = 1e18 + 27092008; const int N = 4e5 + 5; vector<int> initG[N]; class SegmentTree { private: int sizeTree; vector<int> nodes; int getSum(int id, int l, int r, int u, int v) { if (l > v || r < u) return 0; if (u <= l && r <= v) return nodes[id]; int mid = (l + r) >> 1; return getSum(id << 1, l, mid, u, v) + getSum(id << 1 | 1, mid + 1, r, u, v); } public: SegmentTree(int n = 0): sizeTree(n), nodes(4 * n + 5) {} void update(int pos, int value) { int id = 1, l = 1, r = sizeTree; while(l < r) { int mid = (l + r) >> 1; if (pos > mid) id = (id << 1 | 1), l = mid + 1; else id = (id << 1), r = mid; } nodes[id] += value; while(id) { id >>= 1; nodes[id] = nodes[id << 1] + nodes[id << 1 | 1]; } } int getSum(int u, int v) { return getSum(1, 1, sizeTree, u, v); } } IT; struct DSU_tree { int node; vector<int> par, value; vector<vector<int>> G; DSU_tree(int n = 0): node(n), par(2 * n + 5), value(2 * n + 5), G(2 * n + 5) { REP(i, n) par[i] = i; } int root(int v) { return (par[v] == v ? v : par[v] = root(par[v])); } void unite(int u, int v) { int tmp = u; u = root(u); v = root(v); if (u == v) return; node++; par[u] = par[v] = par[node] = node; value[node] = tmp; G[node].pb(u); G[node].pb(v); } } DST_from_S, DST_from_E; struct Query { int U, V; // range of second subtree int id; Query(int u = 0, int v = 0, int i = 0): U(u), V(v), id(i) {} }; vector<Query> del[N], add[N]; int parS[18][N], tinS[N], toutS[N], e_tourS[N], timerS = 0; int parE[18][N], tinE[N], toutE[N], e_tourE[N], timerE = 0; void dfs_S(int u) { tinS[u] = ++timerS; e_tourS[timerS] = u; for(int v : DST_from_S.G[u]) if (v != parS[0][u]) { parS[0][v] = u; dfs_S(v); } toutS[u] = timerS; } void dfs_E(int u) { tinE[u] = ++timerE; e_tourE[timerE] = u; for(int v : DST_from_E.G[u]) if (v != parE[0][u]) { parE[0][v] = u; dfs_E(v); } toutE[u] = timerE; } void build_DSUtree_from_S(int N) { DST_from_S = DSU_tree(N - 1); RED(i, N) for(int v : initG[i]) if (v > i) DST_from_S.unite(i, v); dfs_S(DST_from_S.node); FOR(j, 1, 17) REP(i, DST_from_S.node) parS[j][i] = parS[j - 1][parS[j - 1][i]]; } void build_DSUtree_from_E(int N) { DST_from_E = DSU_tree(N - 1); REP(i, N) for(int v : initG[i]) if (v < i) DST_from_E.unite(i, v); dfs_E(DST_from_E.node); FOR(j, 1, 17) REP(i, DST_from_E.node) parE[j][i] = parE[j - 1][parE[j - 1][i]]; } int findRoot_from_S(int u, int lower) { // find node contains component using all nodes >= lower RED(j, 18) if (DST_from_S.value[parS[j][u]] >= lower) u = parS[j][u]; return u; } int findRoot_from_E(int u, int upper) { // find node contains component with all nodes <= upper RED(j, 18) if (DST_from_E.value[parE[j][u]] <= upper) u = parE[j][u]; return u; } vector<int> check_validity(int N, vector<int> X, vector<int> Y, vector<int> S, vector<int> E, vector<int> L, vector<int> R) { int M = X.size(), Q = S.size(); REP(i, M) { initG[X[i]].pb(Y[i]); initG[Y[i]].pb(X[i]); } build_DSUtree_from_S(N); build_DSUtree_from_E(N); REP(i, Q) { int subtree_S = findRoot_from_S(S[i], L[i]); int subtree_E = findRoot_from_E(E[i], R[i]); int L = tinS[subtree_S], R = toutS[subtree_S]; int U = tinE[subtree_E], V = toutE[subtree_E]; // check if there is a common value in e_tourS[L...R] and e_tourE[U...V] del[L - 1].emplace_back(U, V, i); add[R].emplace_back(U, V, i); } vector<int> ans(Q); IT = SegmentTree(DST_from_S.node); FOR(i, 1, DST_from_S.node) { int node = e_tourS[i]; if (node < N) { IT.update(tinE[node], +1); } // sum(L, R) = sum(1, R) - sum(1, L - 1) for(auto query : del[i]) ans[query.id] -= IT.getSum(query.U, query.V); for(auto query : add[i]) ans[query.id] += IT.getSum(query.U, query.V); } for(int &i : ans) minimize(i, 1); return ans; } //int main() { // ios_base::sync_with_stdio(0); // cin.tie(0); cout.tie(0); // vector<int> ans = check_validity(6, {5, 1, 1, 3, 3, 5}, {1, 2, 3, 4, 0, 2}, // {4, 4, 5}, {2, 2, 4}, {1, 2, 3}, {2, 2, 4}); // for(int x : ans) cout << x << ' '; // 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...