Submission #290094

#TimeUsernameProblemLanguageResultExecution timeMemory
290094model_codeSpring cleaning (CEOI20_cleaning)C++17
100 / 100
261 ms32372 KiB
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>

using namespace std;

/*
LCA solution, it works when you don't know the ith question before answering the i-1th
Note that this is an O(NlogN) solution

Made for you by Mate Busa
*/

int N, Q, a, b, cur, num, o, ans, root, dif, last, level, oo;
vector<int> neighbour[200000];
bool visited[200000];
int dis[200000];
int parent[200000];
int order[200000][2];
int number[200000];
int dp[200000];
int fia[200000];
int f[200000];
vector<int> d[200000];
set<int> reuse;
set<int> who;
vector<int> vec;

void dfs(int x){
    visited[x] = true; order[x][0] = cur++; oo++;
    if(root==x){
        parent[x] = -1;
    } else {
        int hat = 0; while((1<<hat)<=dis[x]) hat++;
        d[x].resize(hat); d[x][0] = parent[x];
        for(int i=1; i<hat; i++) d[x][i] = d[d[x][i-1]][i-1];
    }
    bool lv = true;
    for(int i:neighbour[x]){
        if(!visited[i]){
            dis[i] = dis[x]+1; parent[i] = x;
            dfs(i); lv = false; dp[x] += dp[i];
        }
    }
    if(lv) dp[x]++;
    if(dp[x]%2==0) o++;
    order[x][1] = cur++;
}
void pre(int x){
    for(int i:neighbour[x]){
        if(parent[x]!=i){
            dp[i] = dp[i]%2 + dp[x];
            pre(i);
        }
    }
}
int lca(int x, int y){
    if(dis[y]<dis[x]) swap(x,y);
    for(int i=d[y].size()-1; dis[x]!=dis[y]; i--){
        if(dis[y]-(1<<i)>=dis[x]) y = d[y][i];
    }
    if(x==y) return x;
    for(int i=d[x].size()-1; parent[x]!=parent[y]; i--){
        if((1<<i)<=dis[x] && d[x][i]!=d[y][i]){x = d[x][i]; y = d[y][i];}
    }
    return parent[x];
}

bool smaller(int x, int y){
    return order[x][dif] < order[y][dif];
}

int calc(int x){
    return (dp[x]-(dis[x]+1-dp[x]));
}
///find parent in LCA tree
void up(){
    if(number[a]%2==1){
        ans += calc(a);
        if(f[a]!=-1)  ans -= calc(f[a]);
    }
    if(f[a]!=-1) number[f[a]] += number[a];
    a = f[a];
}

int main()
{
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr); std::cout.tie(nullptr);

    cin >> N >> Q;
    for(int i=0; i<N-1; i++){
        cin >> a >> b;
        neighbour[a-1].push_back(b-1);
        neighbour[b-1].push_back(a-1);
    }
    ///find an inside point
    for(int i=0; i<N; i++) if(neighbour[i].size()!=1) {root = i; break;}

    dfs(root); level = dp[root];
    dp[root] %= 2; pre(root);

    for(int ii=0; ii<Q; ii++){
        reuse.clear(); vec.clear(); who.clear(); ans = N-1+o;
        cin >> num; ans += num;
        for(int i=0; i<num; i++){
            cin >> a; number[a-1]++; reuse.insert(a-1);
        }
        for(int i:reuse){
            if((neighbour[i].size()==1 && number[i]>=2 && number[i]%2==0) || (neighbour[i].size()>1 && number[i]%2==1)){
                vec.push_back(i); number[i] = 1;
            } else {
                number[i] = 0;
            }
        }
        if((level+vec.size())%2==1){
            cout << -1 << '\n';
            for(int i:vec) number[i] = 0;
        } else {
            if(vec.size()!=0){
                dif = 1; sort(vec.begin(),vec.end(),smaller);
                last = -1;
                for(int i:vec){
                    who.insert(i);
                    if(last!=-1) who.insert(lca(last,i));
                    last = i;
                }
                cur = 0;
                for(int i:who) fia[cur++] = i;
                dif = 0; sort(fia,fia+cur,smaller);
                f[fia[0]] = -1; a = fia[0];
                for(int i=1; i<cur; i++){
                    while(order[a][1]<order[fia[i]][0]) up();
                    f[fia[i]] = a; a = fia[i];
                }
                while(a!=-1) up();
                for(int i=0; i<cur; i++) number[fia[i]] = 0;
            }
            cout << ans-1 << '\n';
        }
    }

    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...