Submission #1172687

#TimeUsernameProblemLanguageResultExecution timeMemory
1172687Troll321Spring cleaning (CEOI20_cleaning)C++20
100 / 100
137 ms43028 KiB
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll MAXN = 2e5 + 5; ll n, q, d, initAns, ans = 0, root, parr[MAXN], query[MAXN], plusarr[MAXN]; bool parity[MAXN], isLeaf[MAXN], processed[MAXN]; vector<ll> adjl[MAXN]; ll sz[MAXN], depth[MAXN], heavy[MAXN]; struct segment { ll root = 0; vector<ll> nodes, seg, lazy; ll getIdx(ll node) { return depth[node] - depth[root]; } ll lb() {return 0;} ll rb() {return (ll)nodes.size()-1;} void addNode(ll node) { if(nodes.empty()) {root = node;} nodes.push_back(node); } void build(ll pos, ll l, ll r) { lazy[pos] = 0; if(l == r) { seg[pos] = (parity[nodes[l]]^1); return ; } ll mid = (l+r)/2; build(pos*2, l, mid); build(pos*2+1, mid+1, r); seg[pos] = seg[pos*2] + seg[pos*2+1]; } void init() { seg.resize(nodes.size()*4); lazy.resize(nodes.size()*4); build(1, lb(), rb()); } void updateLazy(ll pos, ll l, ll r) { if(lazy[pos] % 2 == 1) { seg[pos] = (r-l+1) - seg[pos]; } if(l != r) { lazy[pos*2] += lazy[pos]; lazy[pos*2+1] += lazy[pos]; } lazy[pos] = 0; } void update(ll pos, ll l, ll r, ll a, ll b) { updateLazy(pos, l, r); if(l > b || r < a) { return ; } if(a <= l && r <= b) { seg[pos] = (r-l+1) - seg[pos]; if(l != r) { lazy[pos*2]++; lazy[pos*2+1]++; } return ; } ll mid = (l+r)/2; update(pos*2, l, mid, a, b); update(pos*2+1, mid+1, r, a, b); seg[pos] = seg[pos*2] + seg[pos*2+1]; } ll query(ll pos, ll l, ll r, ll idxa, ll idxb) { if(l > idxb || r < idxa) { return 0; } updateLazy(pos, l, r); if(idxa <= l && r <= idxb) { return seg[pos]; } ll mid = (l+r)/2; return ( query(pos*2, l, mid, idxa, idxb) + query(pos*2+1, mid+1, r, idxa, idxb) ); } }; segment segs[MAXN]; void dfs(ll now, ll par) { parity[now] = 0; parr[now] = par; isLeaf[now] = (adjl[now].size() == 1); depth[now] = depth[par]+1; sz[now] = 1; if(isLeaf[now]) {parity[now] = 1;} else { for(ll nxt : adjl[now]) { if(nxt == par) {continue ;} dfs(nxt, now); parity[now] ^= parity[nxt]; sz[now] += sz[nxt]; } } if(parity[now] == 0) {ans++;} } void addHeavy(ll node, ll hidx) { segs[hidx].addNode(node); } void hld(ll now, ll par) { if(!heavy[now]) { heavy[now] = now; addHeavy(now, heavy[now]); } ll mx = -1, nowHeavy = -1; for(ll nxt : adjl[now]) { if(nxt == par) {continue ;} if(sz[nxt] > mx) { mx = sz[nxt]; nowHeavy = nxt; } } if(nowHeavy != -1) { heavy[nowHeavy] = heavy[now]; addHeavy(nowHeavy, heavy[now]); } for(ll nxt : adjl[now]) { if(nxt == par) {continue ;} hld(nxt, now); } } void initSegs() { for (int i = 1; i <= n; ++i) { if(segs[i].nodes.empty()) {continue ;} segs[i].init(); } } void addLeaf(ll node) { segment* s; while(true) { s = &segs[heavy[node]]; (*s).update(1, (*s).lb(), (*s).rb(), 0, (*s).getIdx(node)); if((*s).root == root) {break ;} node = parr[(*s).root]; } } ll ask(ll node) { segment* s; ll out = 0; while(true) { s = &segs[heavy[node]]; out += (*s).query(1, (*s).lb(), (*s).rb(), 0, (*s).getIdx(node)); if((*s).root == root) {break ;} node = parr[(*s).root]; } return out; } ll getRoot() { segment *s = &segs[heavy[root]]; return 1-(*s).query(1, (*s).lb(), (*s).rb(), 0, 0); } void build() { dfs(root, root); hld(root, root); initSegs(); } int main() { ios_base::sync_with_stdio(false); cin.tie(0); cin >> n >> q; ans = n-1; for (int i = 0; i < n-1; ++i) { ll a, b; cin >> a >> b; adjl[a].push_back(b); adjl[b].push_back(a); if(adjl[a].size() > 1) {root = a;} else if(adjl[b].size() > 1) {root = b;} } build(); initAns = ans; while(q--) { // Input ans = initAns; cin >> d; ans += d; for (int i = 0; i < d; ++i) { cin >> query[i]; plusarr[query[i]]++; } for (int i = 0; i < d; ++i) { ll now = query[i]; if(processed[now]) {continue ;} processed[now] = true; if((plusarr[now]-isLeaf[now]) % 2) { // cout << ans << " - " << now << " " << ask(now) << " "; ans -= ask(now); addLeaf(now); ans += ask(now); // cout << ask(now) << " - " << ans << "|\n"; } } if(getRoot() == 1) { cout << "-1\n"; } else { cout << (ans-1) << "\n"; } // Reset for (int i = 0; i < d; ++i) {processed[query[i]] = false;} for (int i = 0; i < d; ++i) { ll now = query[i]; if(processed[now]) {continue ;} processed[now] = true; if((plusarr[now]-isLeaf[now]) % 2) { addLeaf(now); } } for (int i = 0; i < d; ++i) {processed[query[i]] = false; plusarr[query[i]] = 0;} } 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...