제출 #908777

#제출 시각아이디문제언어결과실행 시간메모리
908777NonozeSpring cleaning (CEOI20_cleaning)C++17
100 / 100
353 ms47436 KiB
#include <bits/stdc++.h>
using namespace std;

#define int long long
#define sz(x) (int)(x.size())
const int LOG=25;

int n, q;
vector<vector<int>> adj;
vector<int> depth;
vector<vector<int>> up;
vector<vector<int>> graph;
map<int, int> mp;
vector<int> prefix;
vector<int> parity;
vector<pair<int, int>> isin;
int cntleaf=0, tot=0;
int ans=0;
int begining=0;

bool sortt(int a, int b) {return isin[a].first<isin[b].first;}

void dfsdepth(int s, int lst, int &act) {
	isin[s].first=act++;
	if (adj[s].size()==1) prefix[s]++;
	for (auto u: adj[s]) {
		if (u==lst) continue;
		depth[u]=depth[s]+1;
		up[u][0]=s;
		for (int i=1; i<LOG; i++) {
			up[u][i]=up[ up[u][i-1] ][i-1];
		}
		dfsdepth(u, s, act);
		prefix[s]+=prefix[u];
	}
	isin[s].second=act++;
	return;
}

void dfsparity(int s, int lst=-1) {
	for (auto u: adj[s]) {
		if (u==lst) continue;
		parity[u]=parity[s]+(prefix[u]+1)%2;
		dfsparity(u, s);
	}
	if (lst==-1) tot+=n-1;
	else tot+=(prefix[s]+1)%2;
	return;
}

int dfstot(int s, int lst) {
	int comp=mp[s];
	for (auto u: graph[s]) {
		comp+=dfstot(u, s);
	}
	//if (sz(adj[s])<2) comp++;
	if (comp%2==1) {
		int temp=parity[s], d=depth[s];
		if (lst>=0) temp-=parity[lst], d-=depth[lst];
		ans-=temp;
		ans+=d-temp;
	}
	//if (sz(adj[s])<2) comp--;
	return comp;
}

int lca(int a, int b) {
	if (depth[a]<depth[b]) swap(a, b);
	for (int i=LOG-1; i>=0; i--) {
		if (depth[a]-depth[b] >= (1<<i)) {
			a=up[a][i];
		}
	}
	if (a==b) return a;
	for (int i=LOG-1; i>=0; i--) {
		if (up[a][i]!=up[b][i]) {
			a=up[a][i];
			b=up[b][i];
		}
	}
	return up[a][0];
}


int ALLPROBLEM() {
	int lst=cntleaf;
	while(q--) {
		cntleaf=lst;
		int d; cin >> d;
		mp.clear();
		for (int i=0; i<d; i++) {
			int u; cin >> u, u--;
			if (sz(adj[u])>1 || mp[u]) {
				cntleaf++;
			} else mp[u]++;
			mp[u]++;
		}
		if (cntleaf%2==1) {
			cout << -1 << endl;
			continue;
		}
		vector<int> change;
		for (auto u: mp) {
			if (u.second&1) change.push_back(u.first);
		}
		sort(change.begin(), change.end(), sortt);
		set<int> L;
		for (int i=0; i< sz(change); i++) {
		    L.insert(change[i]);
			if (i!=0) L.insert(lca(change[i], change[i-1]));
		}
		vector<int> vec;
		for (auto u=L.begin(); u!=L.end(); u++) {
			vec.push_back(*u);
		}
		sort(vec.begin(), vec.end(), sortt);
		stack<int> act;
		if (!vec.empty() && vec[0]!=begining) act.push(begining);
		for (auto u: vec) {
			while (!act.empty() && isin[act.top()].second<isin[u].first) act.pop();
			if (!act.empty() && act.top()!=u) graph[act.top()].push_back(u);
			act.push(u);
		}
		ans=tot+d;
		if (!vec.empty()) dfstot(vec[0], begining);
		cout << ans << endl;
		for (auto u: vec) graph[u].clear();
		graph[begining].clear();
	}
	return 0;
}

int solve() {
	cin >> n >> q;
	adj.resize(n);
	graph.resize(n);
	up.resize(n, vector<int> (LOG, 0));
	depth.resize(n, 0);
	prefix.resize(n, 0);
	parity.resize(n, 0);
	isin.resize(n);
	for (int i=0; i<n-1; i++) {
		int u, v; cin >> u >> v;
		u--, v--;
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	for (auto u: adj) if (sz(u)==1) cntleaf++;
	int temp=0;
	begining=0;
	dfsdepth(begining, -1, temp);

	dfsparity(begining);
	return ALLPROBLEM();
}


signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	solve();
	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...