Submission #292937

#TimeUsernameProblemLanguageResultExecution timeMemory
292937arnold518Spring cleaning (CEOI20_cleaning)C++14
100 / 100
306 ms36152 KiB
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int MAXN = 2e5;

int N, Q, M;
vector<int> adj[MAXN+10];
int dp[MAXN+10], par[MAXN+10][30], dep[MAXN+10], leaf, cnt[MAXN+10], val, root;
int L[MAXN+10], R[MAXN+10], dfn;
pii dp2[MAXN+10];

void dfs(int now, int bef, int d)
{
	L[now]=++dfn;
	par[now][0]=bef;
	dep[now]=d;
	dp[now]=0;
	if(adj[now].size()==1)
	{
		dp[now]=1;
		R[now]=dfn;
		return;
	}
	for(int nxt : adj[now])
	{
		if(nxt==bef) continue;
		dfs(nxt, now, d+1);
		dp[now]+=dp[nxt];
		dp[now]%=2;
	}
	R[now]=dfn;
}

pii operator + (const pii &p, const pii &q) { return {p.first+q.first, p.second+q.second}; }
pii operator - (const pii &p, const pii &q) { return {p.first-q.first, p.second-q.second}; }

void dfs2(int now, int bef, pii val)
{
	if(now!=bef)
	{
		if(dp[now]==0) val.first++;
		else if(dp[now]==1) val.second++;
	}
	dp2[now]=val;
	for(int nxt : adj[now])
	{
		if(nxt==bef) continue;
		dfs2(nxt, now, val);
	}
}

int lca(int u, int v)
{
	if(dep[u]>dep[v]) swap(u, v);
	for(int i=20; i>=0; i--) if(dep[par[v][i]]>=dep[u]) v=par[v][i];
	if(u==v) return u;
	for(int i=20; i>=0; i--) if(par[u][i]!=par[v][i]) u=par[u][i], v=par[v][i];
	return par[u][0];
}

int dp3[MAXN+10];
vector<int> adj2[MAXN+10];
int ans=0;

void dfs3(int now, int bef)
{
	for(int nxt : adj2[now])
	{
		if(nxt==bef) continue;
		//printf("Edge %d %d\n", nxt, now);
		dfs3(nxt, now);
		dp3[now]+=dp3[nxt];
		dp3[now]%=2;
	}
	//printf("%d : %d / %d %d\n", now, dp3[now], dp2[now].first, dp2[now].second);
	if(now!=bef)
	{
		if(dp3[now])
		{
			pii t=dp2[now]-dp2[bef];
			ans-=t.first*2+t.second;
			ans+=t.first+t.second*2;
		}
	}
}

int main()
{
	scanf("%d%d", &N, &Q);
	for(int i=1; i<N; i++)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		adj[u].push_back(v);
		adj[v].push_back(u);
	}

	for(int i=1; i<=N; i++) if(adj[i].size()==1) leaf++;

	for(int i=1; i<=N; i++) if(adj[i].size()!=1) { root=i; break; }
	dfs(root, root, 1);
	dfs2(root, root, pii(0, 0));
	
	for(int i=1; i<=N; i++)
	{
		if(i==root) continue;
		if(dp[i]==0) val+=2;
		else val+=1;
	}
	for(int j=1; j<=20; j++) for(int i=1; i<=N; i++) par[i][j]=par[par[i][j-1]][j-1];

	while(Q--)
	{
		scanf("%d", &M);
		vector<int> V, V2;
		for(int i=1; i<=M; i++)
		{
			int t;
			scanf("%d", &t);
			V.push_back(t);
		}

		sort(V.begin(), V.end()); V2=V;
		V2.erase(unique(V2.begin(), V2.end()), V2.end());

		int lt=leaf;
		for(auto it : V2) if(adj[it].size()==1) lt--;
		lt+=M;

		if(lt%2) { printf("-1\n"); continue; }

		for(auto it : V) cnt[it]++;

		vector<int> VV=V2;
		sort(VV.begin(), VV.end(), [&](const int &p, const int &q){ return L[p]<L[q]; });

		int t=VV.size();
		for(int i=0; i+1<t; i++) VV.push_back(lca(VV[i], VV[i+1]));
		VV.push_back(root);

		sort(VV.begin(), VV.end(), [&](const int &p, const int &q){ return L[p]<L[q]; });
		VV.erase(unique(VV.begin(), VV.end()), VV.end());

		vector<int> S;
		for(int i=0; i<VV.size(); i++)
		{
			while(!S.empty() && !(L[S.back()]<=L[VV[i]] && R[VV[i]]<=R[S.back()])) S.pop_back();
			if(!S.empty()) adj2[S.back()].push_back(VV[i]);
			S.push_back(VV[i]);
		}

		for(auto it : V2)
		{
			if(adj[it].size()==1) dp3[it]=(cnt[it]-1)%2;
			else dp3[it]=cnt[it]%2;
		}

		ans=val+M;
		dfs3(root, root);

		printf("%d\n", ans);

		for(auto it : V) cnt[it]=0;
		for(auto it : VV) adj2[it].clear();
		for(auto it : VV) dp3[it]=0;
	}
}

Compilation message (stderr)

cleaning.cpp: In function 'int main()':
cleaning.cpp:149:17: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  149 |   for(int i=0; i<VV.size(); i++)
      |                ~^~~~~~~~~~
cleaning.cpp:93:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   93 |  scanf("%d%d", &N, &Q);
      |  ~~~~~^~~~~~~~~~~~~~~~
cleaning.cpp:97:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   97 |   scanf("%d%d", &u, &v);
      |   ~~~~~^~~~~~~~~~~~~~~~
cleaning.cpp:118:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  118 |   scanf("%d", &M);
      |   ~~~~~^~~~~~~~~~
cleaning.cpp:123:9: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  123 |    scanf("%d", &t);
      |    ~~~~~^~~~~~~~~~
#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...