답안 #814838

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
814838 2023-08-08T10:28:03 Z finn__ Spring cleaning (CEOI20_cleaning) C++17
35 / 100
158 ms 14900 KB
#include <bits/stdc++.h>
using namespace std;

template <size_t L>
struct Segtree
{
    int t[L << 1];
    bitset<L << 1> lzy;

    void set(size_t i, int x) { t[i + L] = x; }

    void build()
    {
        for (size_t i = L - 1; i; --i)
            t[i] = t[i << 1] + t[i << 1 | 1];
    }

    void propagate(size_t k, size_t a, size_t b)
    {
        if (lzy[k])
        {
            lzy[k << 1] = !lzy[k << 1];
            lzy[k << 1 | 1] = !lzy[k << 1 | 1];
            t[k << 1] = (b - a + 1) / 2 - t[k << 1];
            t[k << 1 | 1] = (b - a + 1) / 2 - t[k << 1 | 1];
            lzy[k] = 0;
        }
    }

    void flip(size_t i, size_t j, size_t k = 1, size_t a = 0, size_t b = L - 1)
    {
        if (b < i || a > j)
            return;
        if (i <= a && b <= j)
        {
            lzy[k] = !lzy[k];
            t[k] = b - a + 1 - t[k];
        }
        else
        {
            propagate(k, a, b);
            flip(i, j, k << 1, a, (a + b) >> 1);
            flip(i, j, k << 1 | 1, ((a + b) >> 1) + 1, b);
            t[k] = t[k << 1] + t[k << 1 | 1];
        }
    }

    int sum(size_t i, size_t j, size_t k = 1, size_t a = 0, size_t b = L - 1)
    {
        if (b < i || a > j)
            return 0;
        if (i <= a && b <= j)
            return t[k];
        propagate(k, a, b);
        return sum(i, j, k << 1, a, (a + b) >> 1) + sum(i, j, k << 1 | 1, ((a + b) >> 1) + 1, b);
    }
};

template <size_t N>
struct Hld
{
    vector<size_t> g[N];
    size_t root[N], parent[N], subtree_size[N], ind[N];
    Segtree<N> tree;

    void add_edge(size_t u, size_t v)
    {
        g[u].push_back(v);
        g[v].push_back(u);
    }

    void build()
    {
        memset(parent, 255, sizeof parent);
        find_heavy(0);
        find_root(0);
        init_segtree(0);
        tree.build();
    }

    void find_heavy(size_t u)
    {
        subtree_size[u] = 1;
        for (auto &v : g[u])
            if (v != parent[u])
            {
                parent[v] = u;
                find_heavy(v);
                subtree_size[u] += subtree_size[v];

                if (g[u][0] == parent[u] || subtree_size[v] > subtree_size[g[u][0]])
                    swap(v, g[u][0]);
            }
    }

    size_t find_root(size_t u, size_t i = 0)
    {
        ind[u] = i++;
        for (auto const &v : g[u])
            if (v != parent[u])
            {
                root[v] = v == g[u][0] ? root[u] : v;
                i = find_root(v, i);
            }
        return i;
    }

    bool init_segtree(size_t u)
    {
        bool leaf_parity = g[u].size() == 1;
        for (auto const &v : g[u])
            if (v != parent[u])
                leaf_parity ^= init_segtree(v);
        tree.set(ind[u], leaf_parity);
        return leaf_parity;
    }

    void update_root_path(size_t u)
    {
        while (u != SIZE_MAX)
        {
            tree.flip(ind[root[u]], ind[u]);
            u = parent[root[u]];
        }
    }
};

constexpr size_t N = 1 << 17;

Hld<N> h;
size_t a[N];
bitset<N> no_leaf_anymore;

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    size_t n, q;
    cin >> n >> q;
    for (size_t i = 0; i < n - 1; ++i)
    {
        size_t u, v;
        cin >> u >> v;
        h.add_edge(u - 1, v - 1);
    }

    h.build();

    size_t num_leafs = 0;
    for (size_t i = 0; i < n; ++i)
        num_leafs += h.g[i].size() == 1;

    while (q--)
    {
        size_t d;
        cin >> d;
        for (size_t i = 0; i < d; ++i)
        {
            cin >> a[i], --a[i];
            if (h.g[a[i]].size() > 1 || no_leaf_anymore[a[i]])
                num_leafs++;
            else if (h.g[a[i]].size() == 1)
                no_leaf_anymore[a[i]] = 1;
        }
        for (size_t i = 0; i < d; ++i)
            no_leaf_anymore[a[i]] = 0;

        if (!(num_leafs & 1))
        {
            for (size_t i = 0; i < d; ++i)
                if (h.g[a[i]].size() > 1 || no_leaf_anymore[a[i]])
                    h.update_root_path(a[i]);
                else if (h.g[a[i]].size() == 1)
                    no_leaf_anymore[a[i]] = 1;
            for (size_t i = 0; i < d; ++i)
                no_leaf_anymore[a[i]] = 0;

            cout << 2 * (n - 1) + d - h.tree.sum(0, n - 1) << '\n';

            for (size_t i = 0; i < d; ++i)
                if (h.g[a[i]].size() > 1 || no_leaf_anymore[a[i]])
                    h.update_root_path(a[i]);
                else if (h.g[a[i]].size() == 1)
                    no_leaf_anymore[a[i]] = 1;
            for (size_t i = 0; i < d; ++i)
                no_leaf_anymore[a[i]] = 0;
        }
        else
        {
            cout << "-1\n";
        }

        for (size_t i = 0; i < d; ++i)
            num_leafs -= h.g[a[i]].size() > 1;
    }
}
# 결과 실행 시간 메모리 Grader output
1 Correct 2 ms 4948 KB Output is correct
2 Incorrect 41 ms 6324 KB Output isn't correct
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 42 ms 5812 KB Output is correct
2 Correct 7 ms 6112 KB Output is correct
3 Correct 31 ms 12408 KB Output is correct
4 Correct 46 ms 11328 KB Output is correct
5 Correct 47 ms 13584 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 36 ms 6100 KB Output is correct
2 Correct 10 ms 6076 KB Output is correct
3 Correct 39 ms 14900 KB Output is correct
4 Correct 83 ms 14672 KB Output is correct
5 Correct 41 ms 14020 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Incorrect 41 ms 6740 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 43 ms 9904 KB Output is correct
2 Incorrect 101 ms 9664 KB Output isn't correct
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 158 ms 11892 KB Output is correct
2 Correct 70 ms 13900 KB Output is correct
3 Correct 132 ms 12752 KB Output is correct
4 Correct 77 ms 13340 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 2 ms 4948 KB Output is correct
2 Incorrect 41 ms 6324 KB Output isn't correct
3 Halted 0 ms 0 KB -