제출 #1271592

#제출 시각아이디문제언어결과실행 시간메모리
1271592LucaLucaMSpring cleaning (CEOI20_cleaning)C++20
100 / 100
168 ms18500 KiB
#include <iostream> #include <vector> #include <algorithm> #include <cassert> #pragma GCC optimize("O3") // migrata de pe cses, sper ca intra si aici using ll = long long; #define debug(x) #x << " = " << x << '\n' const int MAXN = 1e5; std::vector<int> g[MAXN + 1]; void dfs0(int u, int p = -1) { if (p != -1) { g[u].erase(std::find(g[u].begin(), g[u].end(), p)); } for (int v : g[u]) { dfs0(v, u); } } // ok acum s a redus la chestii de forma: lanturile astea le xorezi cu 1, spune suma namespace AINT { struct Node { int cnt1, lazy; Node() : cnt1(0), lazy(0) {} Node operator + (const Node &other) const { Node ret; ret.cnt1 = cnt1 + other.cnt1; ret.lazy = 0; return ret; }; }; Node aint[4 * MAXN + 1]; void push(int node, int tl, int tr) { if (aint[node].lazy) { if (tl != tr) { aint[2 * node].lazy ^= 1; aint[2 * node + 1].lazy ^= 1; } aint[node].cnt1 = tr - tl + 1 - aint[node].cnt1; aint[node].lazy = 0; } } void update(int node, int tl, int tr, int l, int r) { push(node, tl, tr); if (l <= tl && tr <= r) { aint[node].lazy ^= 1; } else { int mid = (tl + tr) / 2; if (l <= mid) { update(2 * node, tl, mid, l, r); } if (mid < r) { update(2 * node + 1, mid + 1, tr, l, r); } push(2 * node, tl, mid); push(2 * node + 1, mid + 1, tr); aint[node] = aint[2 * node] + aint[2 * node + 1]; } } int pointQuery(int node, int tl, int tr, int p) { push(node, tl, tr); if (tl == tr) { return aint[node].cnt1; } else { int mid = (tl + tr) / 2; if (p <= mid) { return pointQuery(2 * node, tl, mid, p); } else { return pointQuery(2 * node + 1, mid + 1, tr, p); } } } int query() { push(1, 1, MAXN); return aint[1].cnt1; } }; namespace HLD { int tin[MAXN + 1]; int head[MAXN + 1]; int label[MAXN + 1]; int sz[MAXN + 1]; int heavySon[MAXN + 1]; int parent[MAXN + 1]; int timer = 0; int no_paths = 0; void dfs(int u) { sz[u] = 1; heavySon[u] = -1; for (int v : g[u]) { dfs(v); parent[v] = u; sz[u] += sz[v]; if (heavySon[u] == -1 || sz[v] > sz[heavySon[u]]) { heavySon[u] = v; } } } void dfs2(int u) { tin[u] = ++timer; if (heavySon[u] != -1) { dfs2(heavySon[u]); label[u] = label[heavySon[u]]; } else { label[u] = ++no_paths; } head[label[u]] = u; for (int v : g[u]) { if (v != heavySon[u]) { dfs2(v); } } } void init(int root) { dfs(root); dfs2(root); } void flipRange(int l, int r) { AINT::update(1, 1, MAXN, l, r); } void verticalUpdate(int u) { while (u) { flipRange(tin[head[label[u]]], tin[u]); u = parent[head[label[u]]]; } } int pointQuery(int p) { return AINT::pointQuery(1, 1, MAXN, tin[p]); } int query() { return AINT::query(); } }; int main() { std::ios_base::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); int n, q; std::cin >> n >> q; for (int i = 1; i < n; i++) { int u, v; std::cin >> u >> v; g[u].push_back(v); g[v].push_back(u); } int root = -1; for (int i = 1; i <= n; i++) { if ((int) g[i].size() >= 2) { root = i; } } assert(root != -1); dfs0(root); HLD::init(root); for (int i = 1; i <= n; i++) { if (g[i].empty()) { HLD::verticalUpdate(i); } } while (q--) { int k; std::cin >> k; std::vector<int> vert(k); int answer = 0; for (int &x : vert) { std::cin >> x; if (!g[x].empty()) { HLD::verticalUpdate(x); } g[x].push_back(0); answer++; } int cnt1 = HLD::query(); int cnt2 = n - cnt1; answer += cnt1; answer += 2 * cnt2; if (HLD::pointQuery(root)) { answer = -1; } else { answer -= 2; } // hbrnm ce se intampla in sursa asta, Doamne ajuta!! std::cout << answer << '\n'; for (int x : vert) { g[x].pop_back(); if (!g[x].empty()) { HLD::verticalUpdate(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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...