Submission #885182

#TimeUsernameProblemLanguageResultExecution timeMemory
885182SkillIssueWAGuySpring cleaning (CEOI20_cleaning)C++14
54 / 100
102 ms34120 KiB
#include<vector>
#include<iostream>
#include<utility>
#include<algorithm>
#include<cmath>
using namespace std;
namespace fake{
    std::vector<std::vector<int>> tree;
    std::vector<int> incount, dp, flips, normals, full, parent;
    void setup(int n){
        tree = std::vector<std::vector<int>>(n, std::vector<int>(0));
        dp = parent = std::vector<int>(n, -1);
        incount = std::vector<int>(n, 0);
    }
    void dfs(int node){
        if (tree[node].size() == 0){
            dp[node] = 1;
            if (incount[node] == -1){
                dp[node] = 0;
            }
            return;
        }
        dp[node] = 0;
        for (int i : tree[node]){
            dfs(i);
            dp[node] += dp[i];
        }
        dp[node] %= 2;
        if (incount[node] == -2){
            dp[node] = 1 - dp[node];
        }
        return;
    }
}
vector<vector<int>> tree;
vector<vector<pair<int,int>>> bptrs;
vector<int> dp, dfsorder, dfspos, input, depth, parent, tsize;
vector<bool> isleaf;
int N, Q, D, logN, output, lcount, root;
void dfs(int node){
    dfspos[node] = dfsorder.size();
    dfsorder.push_back(node);
    tsize[node] = 1;
    if (isleaf[node]){
        dp[node] = 1;
        return;
    }
    dp[node] = 0;
    for (int i : tree[node]){
        if (depth[i] == -1){
            depth[i] = depth[node] + 1;
            parent[i] = node;
            dfs(i);
            dp[node] += dp[i];
            tsize[node] += tsize[i];
        }
    }
    dp[node] %= 2;
    return;
}
bool Comp(int a, int b){
    return dfspos[a] < dfspos[b];
}
pair<int,int> LCA(int a, int b){
    int out = 0;
    if (depth[a] < depth[b]){
        int c = a;
        a = b;
        b = c;
    }
    for (int j = logN-1; j >= 0; j--){
        if (depth[bptrs[j][a].first] >= depth[b]){
            out += bptrs[j][a].second;
            a = bptrs[j][a].first;
        }
    }
    if (a == b){
        return {a, out};
    }
    for (int j = logN-1; j >= 0; j--){
        if (bptrs[j][a].first != bptrs[j][b].first){
            out += bptrs[j][a].second + bptrs[j][b].second;
            a = bptrs[j][a].first;
            b = bptrs[j][b].first;
        }
    }
    out += bptrs[0][a].second + bptrs[0][b].second;
    return {bptrs[0][a].first, out};
}
int docase(){
    int out = output + input.size(), lnew;
    for (int i : input){
        if (fake::full.size() == 0){
            fake::full.push_back(i);
        }
        else if (fake::full.back() != i){
            fake::full.push_back(i);
        }
        fake::incount[i] ++;
    }
    for (int i : fake::full){
        if ((fake::incount[i] % 2 == 1) != isleaf[i]){
            fake::flips.push_back(i);
            fake::incount[i] = -2;
        }
        else {
            fake::incount[i] = 0;
        }
    }
    if (!fake::incount[root]){
        fake::normals.push_back(root);
        fake::full.push_back(root);
        fake::incount[root] = -1;
    }
    if (fake::flips.size() > 1){
        for (int i = 0; i < fake::flips.size() - 1; i++){
            int a = LCA(fake::flips[i], fake::flips[i+1]).first;
            if (!fake::incount[a]){
                fake::incount[a] = -1;
                fake::normals.push_back(a);
            }
        }
    }
    fake::full.clear();
    for (int i : fake::flips){
        fake::full.push_back(i);
    }
    for (int i : fake::normals){
        fake::full.push_back(i);
    }
    sort(fake::full.begin(), fake::full.end(), Comp);
    // make the tree
    fake::parent[root] = root;
    int cur = root;
    for (int i : fake::full){
        while (dfspos[i] > dfspos[cur] + tsize[cur] - 1){
            cur = fake::parent[cur];
        }
        fake::parent[i] = cur;
        if (cur != i){
            fake::tree[cur].push_back(i);
        }
        cur = i;
    }
    fake::dfs(root);
    if (dp[root] != fake::dp[root]){
        out = -1;
    }
    else {
        for (int i : fake::full){
            if (fake::dp[i] == 1){
                out += LCA(i, fake::parent[i]).second;
            }
        }
    }
    // finish
    for (int i : fake::full){
        fake::incount[i] = 0;
        fake::tree[i].clear();
        fake::dp[i] = -1;
        fake::parent[i] = -1;
    }
    fake::full.clear();
    fake::flips.clear();
    fake::normals.clear();
    return out;
}
int main(){
    cin.sync_with_stdio(false);
    cin.tie(0);
    cin >> N >> Q;
    output = lcount = 0;
    logN = ceil(log2(N)) + 2;
    tree = vector<vector<int>>(N, vector<int>(0));
    isleaf = vector<bool>(N, false);
    bptrs = vector<vector<pair<int,int>>>(logN, vector<pair<int,int>>(N, {0,0}));
    tsize = parent = dp = dfspos = depth = vector<int>(N, -1);
    fake::setup(N);
    for (int i = 0; i < N-1; i++){
        int a, b;
        cin >> a >> b;
        a--;
        b--;
        tree[a].push_back(b);
        tree[b].push_back(a);
    }
    root = -1;
    for (int i = 0; i < N; i++){
        if (tree[i].size() == 1){
            isleaf[i] = true;
            lcount ++;
        }
        else if (root == -1){
            root = i;
        }
    }
    depth[root] = 0;
    parent[root] = root;
    dfs(root);
    for (int i = 0; i < N; i++){
        bptrs[0][i] = {parent[i], -1 + 2 * dp[i]};
        output += 2 - dp[i];
    }
    bptrs[0][root] = {root, 0};
    output -= 2 - dp[root];
    for (int i = 1; i < logN; i++){
        for (int j = 0; j < N; j++){
            bptrs[i][j] = {bptrs[i-1][bptrs[i-1][j].first].first, bptrs[i-1][j].second + bptrs[i-1][bptrs[i-1][j].first].second};
        }
    }
    bptrs[0][0] = {0, 0};
    for (int i = 0; i < Q; i++){
        input = {};
        cin >> D;
        int v;
        for (int j = 0; j < D; j++){
            cin >> v;
            v--;
            input.push_back(v);
        }
        sort(input.begin(), input.end(), Comp);
        cout << docase() << '\n';;
    }
    return 0;
}

Compilation message (stderr)

cleaning.cpp: In function 'int docase()':
cleaning.cpp:116:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  116 |         for (int i = 0; i < fake::flips.size() - 1; i++){
      |                         ~~^~~~~~~~~~~~~~~~~~~~~~~~
cleaning.cpp:91:38: warning: unused variable 'lnew' [-Wunused-variable]
   91 |     int out = output + input.size(), lnew;
      |                                      ^~~~
#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...