Advertisement
erek1e

CEOI '20 - Spring cleaning

Jul 7th, 2023
705
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.50 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. vector<vector<int>> g;
  6.  
  7. // Segment tree
  8. class Node {
  9. private:
  10.     int even = 0, odd = 0;
  11.     bool prop = false;
  12.     Node * left, * right;
  13.     void propagate(int l, int r) {
  14.         int mid = (l + r) / 2;
  15.         if (!left) left = new Node(), left->even = mid-l;
  16.         if (!right) right = new Node(), right->even = r-mid;
  17.         if (prop) {
  18.             left->prop = !left->prop;
  19.             swap(left->even, left->odd);
  20.             right->prop = !right->prop;
  21.             swap(right->even, right->odd);
  22.             prop = false;
  23.         }
  24.     }
  25. public:
  26.     void rangeToggle(int l, int r, int ql, int qr) { // flips even and odd nodes in a range
  27.         if (qr <= l || r <= ql) return;
  28.         else if (ql <= l && r <= qr) {
  29.             prop = !prop;
  30.             swap(even, odd);
  31.         } else {
  32.             propagate(l, r);
  33.             int mid = (l + r) / 2;
  34.             left->rangeToggle(l, mid, ql, qr);
  35.             right->rangeToggle(mid, r, ql, qr);
  36.             even = left->even + right->even;
  37.             odd = left->odd + right->odd;
  38.         }
  39.     }
  40.     int rangeEven(int l, int r, int ql, int qr) { // counts number of even in a range
  41.         if (qr <= l || r <= ql) return 0;
  42.         else if (ql <= l && r <= qr) return even;
  43.         else {
  44.             propagate(l, r);
  45.             int mid = (l + r) / 2;
  46.             return left->rangeEven(l, mid, ql, qr) + right->rangeEven(mid, r, ql, qr);
  47.         }
  48.     }
  49. };
  50.  
  51. // HLD
  52. vector<int> hldIndex, head, subtree, par;
  53. void getSubtree(int node, int parent = 0) {
  54.     par[node] = parent;
  55.     subtree[node] = 1;
  56.     for (int child : g[node]) {
  57.         if (child == parent) continue;
  58.         getSubtree(child, node);
  59.         subtree[node] += subtree[child];
  60.     }
  61. }
  62. int nextAvailableIndex = 0;
  63. void build(int node, int hd, int parent = 0) {
  64.     hldIndex[node] = nextAvailableIndex++;
  65.     head[node] = hd;
  66.  
  67.     if (g[node].size() == 1 && parent) return;
  68.     int mx = 0;
  69.     if (g[node][0] == parent) mx = 1;
  70.     for (int i = mx+1; i < (int)g[node].size(); ++i) {
  71.         if (g[node][i] == parent) continue;
  72.         if (subtree[g[node][i]] > subtree[g[node][mx]]) mx = i;
  73.     }
  74.     // move mx to front
  75.     while (mx) {
  76.         swap(g[node][mx], g[node][mx-1]);
  77.         --mx;
  78.     }
  79.     // continue dfs as usual
  80.     build(g[node].front(), hd, node);
  81.     for (size_t i = 1; i < g[node].size(); ++i) {
  82.         if (g[node][i] != parent) build(g[node][i], g[node][i], node);
  83.     }
  84. }
  85.  
  86. int main() {
  87.     ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  88.     int n, q; cin >> n >> q;
  89.     g.resize(1+n);
  90.     for (int i = 1; i < n; ++i) {
  91.         int u, v; cin >> u >> v;
  92.         g[u].push_back(v);
  93.         g[v].push_back(u);
  94.     }
  95.  
  96.     int root = 1; // choose non-leaf root
  97.     while (g[root].size() == 1) ++root;
  98.  
  99.     // build HLD
  100.     subtree.resize(1+n), par.resize(1+n);
  101.     getSubtree(root);
  102.     hldIndex.resize(1+n), head.resize(1+n);
  103.     build(root, root);
  104.    
  105.  
  106.     Node * segRoot = new Node(); // segment tree for HLD
  107.     auto toggleToRoot = [&](int a) { // toggle path from a to root
  108.         while (a) {
  109.             int first = hldIndex[head[a]], last = hldIndex[a]; // inclusive
  110.             segRoot->rangeToggle(0, n, first, last+1); // toggle segtree range [first, last]
  111.             a = par[head[a]];
  112.         }
  113.     };
  114.     int originalLeaves = 0;
  115.     for (int i = 1; i <= n; ++i) {
  116.         if (g[i].size() == 1) {
  117.             ++originalLeaves;
  118.             toggleToRoot(i);
  119.         }
  120.     }
  121.    
  122.     while (q--) {
  123.         int D; cin >> D;
  124.         vector<int> a(D);
  125.         for (int &x : a) cin >> x;
  126.  
  127.         int totalLeaves = originalLeaves + D;
  128.         sort(a.begin(), a.end());
  129.         vector<int> noLongerLeaves;
  130.         for (size_t i = 0; i < a.size(); ++i) {
  131.             if (g[a[i]].size() == 1 && (!i || a[i] != a[i-1])) {
  132.                 --totalLeaves;
  133.                 noLongerLeaves.push_back(a[i]);
  134.             }
  135.         }
  136.         if (totalLeaves & 1) {
  137.             cout << "-1\n";
  138.             continue;
  139.         }
  140.  
  141.         for (int &x : a) toggleToRoot(x);
  142.         for (int &x : noLongerLeaves) toggleToRoot(x);
  143.  
  144.         int even = segRoot->rangeEven(0, n, 1, n); // query number of nodes that have an even number of leaves in their subtree
  145.         cout << (n+D-1) + even << '\n'; // cost is 1 on every odd edge, 2 on every even edge
  146.  
  147.         for (int &x : a) toggleToRoot(x);
  148.         for (int &x : noLongerLeaves) toggleToRoot(x);
  149.     }
  150.     return 0;
  151. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement