Submission #967522

#TimeUsernameProblemLanguageResultExecution timeMemory
967522antonSpring cleaning (CEOI20_cleaning)C++17
100 / 100
379 ms42580 KiB
#include<bits/stdc++.h>

using namespace std;
#define pii pair<int, int>

pii combine(pii a, pii b){
    return {a.first +b.first, a.second+b.second};
}
struct SegTree{
    vector<pii> tr;
    vector<int> d;
    int sz= 1;
    
    void init(int len){
        while(sz<len){
            sz*=2;
        }
        tr.resize(2*sz, {0, 0});
        d.resize(2*sz, 0);
    }

    void build(vector<int>&v, int lt, int rt, int t){
        if(lt>=v.size()){
            tr[t] ={0, 0};
        }
        if(lt==rt){
            if(v[lt] ==0){
                tr[t] = {1, 0};
            }
            else{
                tr[t] = {0, 1};
            }
        }
        else{
            int mid = (lt+rt)/2;
            build(v, lt, mid, t*2);
            build(v, mid+1, rt, t*2+1);
            tr[t] = combine(tr[t*2], tr[t*2+1]);
        }
    }

    void push(int id){
        if(d[id]!=0){
            swap(tr[id*2].first, tr[id*2].second);
            swap(tr[id*2+1].first, tr[id*2+1].second);
            d[id] =0;
            d[id*2] ^=1;
            d[id*2+1] ^=1;
        }
    }

    void flip(int l, int r, int lt, int rt, int t){
        
        if(l<= lt && rt<=r){
            d[t]^=1;
            swap(tr[t].first, tr[t].second);
        }
        else if(rt<l || r<lt){
            //cout<<"done "<<endl;
            return;
        }
        else{
            push(t);
            int mid =(lt+rt)/2;
            flip(l, r, lt, mid, t*2);
            flip(l, r, mid+1, rt, t*2+1);
            tr[t] = combine(tr[t*2], tr[t*2+1]);
        }
    }


    pii get(int l, int r, int lt, int rt, int t){
        pii res;
        
        if(rt<l || r<lt){
            res= {0, 0};
        }
        else if(l<= lt && rt<=r){
            
            res= tr[t];
        }
        else{
            push(t);
            int mid = (lt+rt)/2;
            res= combine(get(l, r, lt, mid, t*2), get(l, r, mid+1, rt, t*2+1));
        }
        return res;
    }

    pii change(int l, int r){
        //cout<<"changing on "<<l<<" "<<r<<endl;
        flip(l, r, 0, sz-1, 1);
        return get(l, r, 0, sz-1, 1);
    }
};


struct HLD{

    SegTree seg;
    vector<int> parent, heavy, head, pos, depth, pairdeg;
    vector<vector<int>> adj;
    int cur_pos =0;
    int root =0;

    HLD(int sz, vector<int>& parities, vector<vector<int>> ad, int r){
        root =r;
        parent.resize(sz);
        heavy.resize(sz);
        head.resize(sz);
        pos.resize(sz);
        adj.resize(sz);
        depth.resize(sz);
        pairdeg.resize(sz);
        adj =ad;


        dfs(root, -1, 0);
        decompose(root, root);

        seg.init(sz);

        for(int i = 0; i<sz; i++){
            pairdeg[pos[i]] = parities[i];
        }
        seg.build(pairdeg, 0, seg.sz-1, 1);
    }

    int dfs(int u, int a, int dp){
        depth[u] =dp;
        parent[u] = a;
        int sz= 1;
        int id= -1, maxsz= 0;
        for(auto v: adj[u]){
            if(v!=a){
                int res= dfs(v, u, dp+1);
                if(res>maxsz){
                    id = v;
                    maxsz =res;
                }
                sz+=res;
            }
        }
        heavy[u] = id;
        return sz;
    }

    void decompose(int u, int h){
        head[u] = h;
        pos[u] = cur_pos++;

        if(heavy[u]!=-1){
            decompose(heavy[u], h);
        }
        for(auto v: adj[u]){
            if(v!=heavy[u] && v!=parent[u]){
                decompose(v, v);
            }
        }

    };

    pii change_upwards(int u){
        pii res ={0, 0};
        while(head[u] != root){
            //cout<<"c "<<head[u]<<" "<<u<<endl;
            res = combine(res, seg.change(pos[head[u]], pos[u]));
            u = parent[head[u]];
        }
        
        //cout<<"c "<<root    <<" "<<u<<endl;
        res = combine(res, seg.change(pos[root], pos[u]));
        //cout<<"cres "<<res.first<<" "<<res.second<<endl;
        return res;
    }
};

const int MAX_N = 100000;

vector<vector<int>> adj;
vector<int> parity;
vector<int> cost = {2, 1};

int total_cost= 0;

int count_leaves(int u, int a){
    int s= 0;
    for(auto v: adj[u]){
        if(v!=a){
            s+=count_leaves(v, u);
        }
    }
    if(s==0){
        s=1;
    }
    total_cost+= cost[s%2];
    
    //cout<<u+1<<" "<<s<<endl;
    parity[u] = s%2;
    return s;
}


signed main(){
    cin.tie(NULL);
    ios_base::sync_with_stdio(false);
    int n, k;
    cin>>n>>k;
    adj.resize(n);
    parity.resize(n);

    int node = 0;
    int deg= 0;

    for(int i = 0; i<n-1; i++){
        int a, b;
        cin>>a>>b;
        a--;b--;
        adj[a].push_back(b);
        adj[b].push_back(a);

        if(adj[a].size()>deg){
            node =a;
            deg = adj[a].size();
        }
        if(adj[b].size()>deg){
            node =b;
            deg = adj[b].size();
        }
    }


    int r= count_leaves(node, -1);
    HLD hld(n, parity, adj, node);
    //pii v= hld.seg.get(0, 0, 0, hld.seg.sz-1, 1);
    //cout<<v.first<<" "<<v.second<<endl;

    for(int i = 0; i<k; i++){
        int d;
        cin>>d;
        vector<int> pos(d);
        for(int i = 0; i<d; i++){
            cin>>pos[i];
            pos[i]--;
        }

        for(auto e: pos){
            adj[e].push_back(-1);
            if(adj[e].size()>2){
                pii new_val =hld.change_upwards(e);
                total_cost -= new_val.second * cost[0] + new_val.first * cost[1];
                total_cost += new_val.first * cost[0] + new_val.second * cost[1];
            }
        }

        pii v= hld.seg.get(0, 0, 0, hld.seg.sz-1, 1);
        //cout<<v.first<<" "<<v.second<<endl;
        if(hld.seg.get(0, 0, 0, hld.seg.sz-1, 1) != pair<int, int>({1, 0})){
            cout<<-1<<endl;
        }
        else{
            cout<<total_cost-2 +d<<endl;
        }

        for(auto e: pos){
            if(adj[e].size()>2){
                pii new_val =hld.change_upwards(e);
                total_cost -= new_val.second * cost[0] + new_val.first * cost[1];
                total_cost += new_val.first * cost[0] + new_val.second * cost[1];
            }
            adj[e].pop_back();
        }
        //cout<<"baseline: "<<total_cost-2<<endl;
    }
}

Compilation message (stderr)

cleaning.cpp: In member function 'void SegTree::build(std::vector<int>&, int, int, int)':
cleaning.cpp:23:14: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   23 |         if(lt>=v.size()){
      |            ~~^~~~~~~~~~
cleaning.cpp: In function 'int main()':
cleaning.cpp:222:25: warning: comparison of integer expressions of different signedness: 'std::vector<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  222 |         if(adj[a].size()>deg){
      |            ~~~~~~~~~~~~~^~~~
cleaning.cpp:226:25: warning: comparison of integer expressions of different signedness: 'std::vector<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  226 |         if(adj[b].size()>deg){
      |            ~~~~~~~~~~~~~^~~~
cleaning.cpp:256:13: warning: variable 'v' set but not used [-Wunused-but-set-variable]
  256 |         pii v= hld.seg.get(0, 0, 0, hld.seg.sz-1, 1);
      |             ^
cleaning.cpp:233:9: warning: unused variable 'r' [-Wunused-variable]
  233 |     int r= count_leaves(node, -1);
      |         ^
#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...