Submission #302372

#TimeUsernameProblemLanguageResultExecution timeMemory
302372errorgornSpring cleaning (CEOI20_cleaning)C++14
100 / 100
485 ms34808 KiB
//雪花飄飄北風嘯嘯
//天地一片蒼茫

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;
#define ll long long
#define ii pair<ll,ll>
#define iii pair<ii,ll>
#define fi first
#define se second
#define endl '\n'
#define debug(x) cout << #x << " is " << x << endl

#define rep(x,start,end) for(auto x=(start)-((start)>(end));x!=(end)-((start)>(end));((start)<(end)?x++:x--))
#define all(x) (x).begin(),(x).end()
#define sz(x) (int)(x).size()

#define indexed_set tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
//change less to less_equal for non distinct pbds, but erase will bug

mt19937 rng(chrono::system_clock::now().time_since_epoch().count());


int n,q;
vector<int> al[100005];
int in[100005]; //preorder
int out[100005]; //postorder
int st[100005]; //subtree size
int parent[100005]; //first parent
int hparent[100005]; //parent on heavy path
int depth[100005];

bool par[100005];
int extra[100005];

ll ans;

int dfs(int i,int p){
	int ropes=0;
	if (sz(al[i])==1){
		ans+=depth[i];
		par[i]=true;
		ropes=1;
	}
	
	for (auto &it:al[i]){
		if (it==p) continue;
	
		depth[it]=depth[i]+1;
		ropes+=dfs(it,i);
		par[i]^=par[it];
	}
	
	while (ropes>2){
		ropes-=2;
		ans-=2*depth[i];
	}
	
	return ropes;
}

void dfs_st(int i,int p){
    parent[i]=p;
    st[i]=1;
    if (al[i][0]==p && al[i].size()>1) swap(al[i][0],al[i][1]);
    for (auto &it:al[i]){ ///& is important here
        if (it==p) continue;
        dfs_st(it,i);
        st[i]+=st[it];
        if (st[it]>st[al[i][0]]){
            swap(it,al[i][0]);
            //we ensure heavy child is al[i][0]
        }
    }
}

int dfs_time=0;
void dfs_hld(int i,int p){
    in[i]=++dfs_time;
    for (auto it:al[i]){
        if (it==p) continue;
        hparent[it]=(it==al[i][0])?hparent[i]:it;
        dfs_hld(it,i);
    }
    out[i]=dfs_time;
}

struct node{
	int s,e,m;
	int bits[2];
	bool lazy=false;
	node *l,*r;
	
	node (int _s,int _e){
		s=_s,e=_e,m=s+e>>1;
		bits[0]=bits[1]=0;
		
		if (s!=e){
			l=new node(s,m);
			r=new node(m+1,e);
		}
	}
	
	void init(int i,int k){
		bits[k]++;
		if (s==e) return;
		else if (i<=m) l->init(i,k);
		else r->init(i,k);
	}
	
	void propo(){
		if (lazy){
			swap(bits[0],bits[1]);
			
			if (s!=e){
				l->lazy^=true;
				r->lazy^=true;
			}
			lazy=false;
		}
	}
	
	void update(int i,int j){
		if (s==i && e==j) lazy^=true;
		else{
			if (j<=m) l->update(i,j);
			else if (m<i) r->update(i,j);
			else l->update(i,m),r->update(m+1,j);
			
			l->propo(),r->propo();
			rep(x,0,2) bits[x]=l->bits[x]+r->bits[x];
		}
	}
	
	int query(int i,int j){
		propo();
		if (s==i && e==j) return bits[1];
		else if (j<=m) return l->query(i,j);
		else if (m<i) return r->query(i,j);
		else return l->query(i,m)+r->query(m+1,j);
	}
} *root=new node(0,200005);

void hld_query(int i,bool flag){
    while (i){
		if (flag){
			root->update(in[hparent[i]],in[i]);
			ans-=2*root->query(in[hparent[i]],in[i]);
		}
		else{
			ans+=2*root->query(in[hparent[i]],in[i]);
			root->update(in[hparent[i]],in[i]);
		}
		i=parent[hparent[i]];
	}
	
	if (root->query(in[1],in[1])==flag){
		if (flag) ans+=2;
		else ans-=2;
	}
}

vector<int> v;

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	cin>>n>>q;
	
	int a,b;
	rep(x,1,n){
		cin>>a>>b;
		al[a].push_back(b);
		al[b].push_back(a);
	}
	
	dfs(1,-1);
	//cout<<ans<<endl;
	
	parent[1]=0;
	hparent[1]=1;
	if (n>=2){
    	dfs_st(1,-1);
    	dfs_hld(1,-1);
	}
	
	rep(x,1,n+1) root->init(in[x],par[x]);
	
	while (q--){
		v.clear();
		cin>>a;
		rep(x,0,a){
			cin>>b;
			v.push_back(b);
		}
		
		for (auto &it:v){
			if (sz(al[it])==1 && extra[it]==0){
				ans++;
			}
			else{
				ans+=depth[it]+1;
				hld_query(it,true);
			}
			
			extra[it]++;
		}
		
		if (root->query(in[1],in[1])) cout<<"-1"<<endl;
		else cout<<ans<<endl;
		
		for (auto &it:v){
			extra[it]--;
			
			if (sz(al[it])==1 && extra[it]==0){
				ans--;
			}
			else{
				ans-=depth[it]+1;
				hld_query(it,false);
			}
		}
	}
}

Compilation message (stderr)

cleaning.cpp: In constructor 'node::node(int, int)':
cleaning.cpp:100:16: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  100 |   s=_s,e=_e,m=s+e>>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...