Submission #1080770

# Submission time Handle Problem Language Result Execution time Memory
1080770 2024-08-29T13:55:53 Z RecursiveCo Spring cleaning (CEOI20_cleaning) C++17
26 / 100
110 ms 33504 KB
// CF template, version 3.0

#include <bits/stdc++.h>

using namespace std;

#define improvePerformance ios_base::sync_with_stdio(false); cin.tie(0)
#define getTest int t; cin >> t
#define eachTest for (int _var=0;_var<t;_var++)
#define get(name) int (name); cin >> (name)
#define out(o) cout << (o)
#define getList(cnt, name) vector<int> (name); for (int _=0;_<(cnt);_++) { get(a); (name).push_back(a); }
#define sortl(name) sort((name).begin(), (name).end())
#define rev(name) reverse((name).begin(), (name).end())
#define forto(name, var) for (int (var) = 0; (var) < (name); (var)++)
#define decision(b) if (b){out("YES");}else{out("NO");}

//#define int long long int

template <typename T, typename I>
struct segtree {
    int n;
    vector<T> tree;
    vector<I> initial;
    T id;

    segtree(int i_n, vector<I> i_initial, T i_id): n(i_n), initial(i_initial), id(i_id) {
        tree.resize(4 * n);
    }

    T conquer(T left, T right) {
        // write your conquer function
    }

    T value(I inp) {
        // write your value function
    }

    void build(int v, int l, int r) {
        if (l == r) tree[v] = value(initial[l]);
        else {
            int middle = (l + r) / 2;
            build(2 * v, l, middle);
            build(2 * v + 1, middle + 1, r);
            tree[v] = conquer(tree[2 * v], tree[2 * v + 1]);
        }
    }

    void upd(int v, int l, int r, int i, I x) {
        if (l == r) tree[v] = value(x);
        else {
            int middle = (l + r) / 2;
            if (middle >= i) upd(2 * v, l, middle, i, x);
            else upd(2 * v + 1, middle + 1, r, i, x);
            tree[v] = conquer(tree[2 * v], tree[2 * v + 1]);
        }
    }

    T query(int v, int l, int r, int ql, int qr) {
        if (ql <= l && r <= qr) return tree[v];
        else if (r < ql || qr < l) return id;
        int middle = (l + r) / 2;
        T left = query(2 * v, l, middle, ql, qr);
        T right = query(2 * v + 1, middle + 1, r, ql, qr);
        return conquer(left, right);
    }
};

// vector<int>

// I'm practising virtual trees. I thought of the hld solution myself but yk I really cba to implement it
// so I read the editorial and I found the cool virtual trees solution. Time to practise it
// ~~and get lost in implementation hell for an hour or ten~~

vector<vector<int>> adjList;
vector<int> parity;
vector<int> height;
vector<int> upto;
vector<int> tin;
vector<int> tout;
vector<vector<int>> lift;
int tot = 0;
int timer = 0;
int root;

void dfs1(int v, int p, int h) {
    tin[v] = timer++;
    height[v] = h;
    lift[v][0] = p == -1? v: p;
    forto(18, i) {
        if (i == 0) continue;
        lift[v][i] = lift[lift[v][i - 1]][i - 1];
    }
    for (int con: adjList[v]) {
        if (con == p) continue;
        dfs1(con, v, h + 1);
        if (parity[con] == 0) parity[v] = 1 - parity[v];
    }
    if (adjList[v].size() == 1) parity[v] = 1 - parity[v];
    tout[v] = timer;
}

void dfs2(int v, int p, int sum) {
    sum += parity[v];
    tot += parity[v];
    upto[v] = sum;
    for (int con: adjList[v]) {
        if (con == p) continue;
        dfs2(con, v, sum);
    }
}

int lca(int u, int v) {
    if (height[u] > height[v]) swap(u, v);
    int dif = height[v] - height[u];
    int p = 1;
    forto(18, i) {
        if (dif & p) v = lift[v][i];
        p *= 2;
    }
    // now they're the same height
    if (u == v) return u; // = v
    for (int i = 17; i >= 0; i--) {
        int x = lift[u][i];
        int y = lift[v][i];
        if (x != y) {
            u = x;
            v = y;
        }
    }
    return lift[u][0];
}

int dfs3(int v, int p, vector<int>& actnodes, vector<vector<int>>& tree) {
    int here = 1;
    for (int con: tree[v]) {
        here += dfs3(con, v, actnodes, tree);
    }
    if (here % 2) {
        int parent = p == -1? root: actnodes[p];
        int length = height[actnodes[v]] - height[parent];
        int sum = upto[actnodes[v]] - upto[parent];
        if (p == -1) {
            length++;
            sum += parity[root];
        }
        tot += length - 2 * sum;
    }
    return here;
}

signed main() {
    improvePerformance;
    //getTest;
    
    //eachTest {
        get(n);
        get(q);
        adjList.resize(n);
        parity.resize(n, 1);
        height.resize(n);
        upto.resize(n);
        tin.resize(n);
        tout.resize(n);
        lift.resize(n, vector<int>(18));
        forto(n - 1, i) {
            get(a);
            get(b);
            a--;
            b--;
            adjList[a].push_back(b);
            adjList[b].push_back(a);
        }
        forto(n, i) {
            if (adjList[i].size() != 1) {
                dfs1(i, -1, 1);
                dfs2(i, -1, 0);
                root = i;
                break;
            }
        }
        bool evenleaves = parity[root] == 1;
        int original = tot;
        forto(q, i) {
            get(d);
            map<int, int> cnt;
            // We need to figure out which nodes get their parity flipped.
            int m = n;
            forto(d, i) {
                get(x);
                x--;
                cnt[x]++;
                m++;
            }
            bool works = evenleaves;
            vector<pair<int, int>> flip;
            for (auto it = cnt.begin(); it != cnt.end(); it++) {
                int v = it->first;
                int c = it->second;
                if (adjList[v].size() == 1) c++;
                if (c % 2) flip.push_back({tin[v], v}), works = !works;
            }
            sortl(flip);
            set<pair<int, int>> nodes;
            for (pair<int, int> node: flip) nodes.insert(node);
            int length = flip.size();
            forto(length - 1, i) {
                int here = lca(flip[i].second, flip[i + 1].second);
                nodes.insert({tin[here], here});
            }
            vector<int> actnodes;
            for (auto node: nodes) actnodes.push_back(node.second);
            int k = actnodes.size();
            vector<vector<int>> tree(k);
            stack<int> st;
            int j = 0;
            for (int v: actnodes) {
                while (!st.empty()) {
                    int l = st.top();
                    int u = actnodes[l];
                    if (tin[u] < tin[v] && tout[v] <= tout[u]) break;
                    st.pop();
                }
                if (!st.empty()) {
                    int l = st.top();
                    tree[l].push_back(j);
                }
                st.push(j);
                j++;
            }
            if (k) dfs3(0, -1, actnodes, tree);
            if (works) out(m - 2 + tot);
            else out(-1);
            out("\n");
            tot = original;
        }
    //}
}

Compilation message

cleaning.cpp: In function 'void dfs1(int, int, int)':
cleaning.cpp:15:35: warning: unnecessary parentheses in declaration of 'i' [-Wparentheses]
   15 | #define forto(name, var) for (int (var) = 0; (var) < (name); (var)++)
      |                                   ^
cleaning.cpp:90:5: note: in expansion of macro 'forto'
   90 |     forto(18, i) {
      |     ^~~~~
cleaning.cpp: In function 'int lca(int, int)':
cleaning.cpp:15:35: warning: unnecessary parentheses in declaration of 'i' [-Wparentheses]
   15 | #define forto(name, var) for (int (var) = 0; (var) < (name); (var)++)
      |                                   ^
cleaning.cpp:117:5: note: in expansion of macro 'forto'
  117 |     forto(18, i) {
      |     ^~~~~
cleaning.cpp: In function 'int main()':
cleaning.cpp:10:23: warning: unnecessary parentheses in declaration of 'n' [-Wparentheses]
   10 | #define get(name) int (name); cin >> (name)
      |                       ^
cleaning.cpp:157:9: note: in expansion of macro 'get'
  157 |         get(n);
      |         ^~~
cleaning.cpp:10:23: warning: unnecessary parentheses in declaration of 'q' [-Wparentheses]
   10 | #define get(name) int (name); cin >> (name)
      |                       ^
cleaning.cpp:158:9: note: in expansion of macro 'get'
  158 |         get(q);
      |         ^~~
cleaning.cpp:15:35: warning: unnecessary parentheses in declaration of 'i' [-Wparentheses]
   15 | #define forto(name, var) for (int (var) = 0; (var) < (name); (var)++)
      |                                   ^
cleaning.cpp:166:9: note: in expansion of macro 'forto'
  166 |         forto(n - 1, i) {
      |         ^~~~~
cleaning.cpp:10:23: warning: unnecessary parentheses in declaration of 'a' [-Wparentheses]
   10 | #define get(name) int (name); cin >> (name)
      |                       ^
cleaning.cpp:167:13: note: in expansion of macro 'get'
  167 |             get(a);
      |             ^~~
cleaning.cpp:10:23: warning: unnecessary parentheses in declaration of 'b' [-Wparentheses]
   10 | #define get(name) int (name); cin >> (name)
      |                       ^
cleaning.cpp:168:13: note: in expansion of macro 'get'
  168 |             get(b);
      |             ^~~
cleaning.cpp:15:35: warning: unnecessary parentheses in declaration of 'i' [-Wparentheses]
   15 | #define forto(name, var) for (int (var) = 0; (var) < (name); (var)++)
      |                                   ^
cleaning.cpp:174:9: note: in expansion of macro 'forto'
  174 |         forto(n, i) {
      |         ^~~~~
cleaning.cpp:15:35: warning: unnecessary parentheses in declaration of 'i' [-Wparentheses]
   15 | #define forto(name, var) for (int (var) = 0; (var) < (name); (var)++)
      |                                   ^
cleaning.cpp:184:9: note: in expansion of macro 'forto'
  184 |         forto(q, i) {
      |         ^~~~~
cleaning.cpp:10:23: warning: unnecessary parentheses in declaration of 'd' [-Wparentheses]
   10 | #define get(name) int (name); cin >> (name)
      |                       ^
cleaning.cpp:185:13: note: in expansion of macro 'get'
  185 |             get(d);
      |             ^~~
cleaning.cpp:15:35: warning: unnecessary parentheses in declaration of 'i' [-Wparentheses]
   15 | #define forto(name, var) for (int (var) = 0; (var) < (name); (var)++)
      |                                   ^
cleaning.cpp:189:13: note: in expansion of macro 'forto'
  189 |             forto(d, i) {
      |             ^~~~~
cleaning.cpp:10:23: warning: unnecessary parentheses in declaration of 'x' [-Wparentheses]
   10 | #define get(name) int (name); cin >> (name)
      |                       ^
cleaning.cpp:190:17: note: in expansion of macro 'get'
  190 |                 get(x);
      |                 ^~~
cleaning.cpp:15:35: warning: unnecessary parentheses in declaration of 'i' [-Wparentheses]
   15 | #define forto(name, var) for (int (var) = 0; (var) < (name); (var)++)
      |                                   ^
cleaning.cpp:207:13: note: in expansion of macro 'forto'
  207 |             forto(length - 1, i) {
      |             ^~~~~
# Verdict Execution time Memory Grader output
1 Correct 0 ms 348 KB Output is correct
2 Incorrect 40 ms 5188 KB Output isn't correct
3 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 12 ms 1628 KB Output isn't correct
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 14 ms 2648 KB Output is correct
2 Correct 14 ms 2904 KB Output is correct
3 Correct 50 ms 28480 KB Output is correct
4 Correct 86 ms 33504 KB Output is correct
5 Correct 40 ms 25560 KB Output is correct
# Verdict Execution time Memory Grader output
1 Incorrect 32 ms 5464 KB Output isn't correct
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 58 ms 13504 KB Output is correct
2 Incorrect 68 ms 13636 KB Output isn't correct
3 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 99 ms 20560 KB Output is correct
2 Correct 110 ms 23852 KB Output is correct
3 Correct 92 ms 23892 KB Output is correct
4 Correct 97 ms 23092 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 0 ms 348 KB Output is correct
2 Incorrect 40 ms 5188 KB Output isn't correct
3 Halted 0 ms 0 KB -