Submission #1270217

#TimeUsernameProblemLanguageResultExecution timeMemory
1270217thanhcodedaoSpring cleaning (CEOI20_cleaning)C++20
36 / 100
171 ms22088 KiB
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for(int i = (a), _b = (b); i <= _b; ++i)
#define REP(i, a, b) for(int i = (a), _b = (b); i >= _b; --i)
#define mp make_pair
#define all(v) v.begin(), v.end()
#define uni(v) v.erase(unique(all(v)), v.end())
#define Mask(i) (1 << (i))
#define Bit(x, i) (((x) >> (i)) & 1)
const int mod = 1e9 + 7;
int fastPow(int a, int n){
	if(n == 0) return 1;
	int t = fastPow(a, n >> 1);
	t = 1ll * t * t % mod;
	if(n & 1) t = 1ll * t * a % mod;
	return t;
}
bool minimize(int &u, int v) { return u > v ? u = v, true : false;}
bool maximize(int &u, int v) { return u < v ? u = v, true : false;}
bool minimizell(long long &u, long long v) { return u > v ? u = v, true : false;}
bool maximizell(long long &u, long long v) { return u < v ? u = v, true : false;}
const int maxN = 1e5 + 5;
int n, q;
vector<int> adj[maxN];
vector<int> query[maxN];
int numNode[maxN];
namespace subtask2{
	bool check(){
		return n <= 20000 && q <= 300;
	}
	const int maxN = 20005;
	int orgN;
	long long answer = 0;
	int numLeaves[maxN];
	void dfs(int u, int p){
		numLeaves[u] = 0;
		if(u != 1){
			if(adj[u].size() == 1){
				numLeaves[u] = 1;
				return;
			}
		}
		for(int v : adj[u]){
			if(v == p) continue;
			dfs(v, u);
			answer += numLeaves[v];
			numLeaves[u] += numLeaves[v];
		}
		if(numLeaves[u] % 2 == 1)numLeaves[u] = 1;
		else numLeaves[u] = 2;
	}
	void solve(){
		orgN = n;
		FOR(i, 1, q) {
			n = orgN;
//			for(int u : query[i])cout << u << ' ';cout << '\n';
			for(int u : query[i]){
				adj[u].emplace_back(++n);
				adj[n].emplace_back(u);
			}
			int numLeaves = 0;
			FOR(i, 1, n){
				if(adj[i].size() == 1)++numLeaves;
			}
			if(numLeaves % 2 == 1){
				FOR(i, 1, orgN){
					while(!adj[i].empty() && adj[i].back() > orgN) adj[i].pop_back();
				}
				FOR(i, orgN + 1, n)adj[i].clear();
				cout << -1 << '\n';
				continue;
			}
			answer = 0;
			dfs(1, 0);
			cout << answer << '\n';
			FOR(i, 1, orgN){
				while(!adj[i].empty() && adj[i].back() > orgN) adj[i].pop_back();
			}
			FOR(i, orgN + 1, n)adj[i].clear();
		}
	}
}
namespace ac{
	int numLeaves[maxN];
	long long rem = 0;
	int chain[maxN], curChain = 1, top[maxN], arr[maxN], lab[maxN], curLab = 1, sz[maxN], par[maxN];
	void dfs(int u = 1, int p = 0){
		if(u != 1){
			if(adj[u].size() == 1){
				numLeaves[u] = 1;
				return;
			}
		}
		sz[u] = 1;
		for(int v : adj[u]){
			if(v == p) continue;
			par[v] = u;
			dfs(v, u);
			sz[u] += sz[v];
			numLeaves[u] += numLeaves[v];
			rem += numLeaves[v];
		}
		if(numLeaves[u] % 2 == 0)numLeaves[u] = 2;
		else numLeaves[u] = 1;
	}
	void hld(int u = 1, int p = 0){
		if(top[curChain] == 0) top[curChain] = u;
		chain[u] = curChain;
		lab[u] = curLab;
		arr[curLab] = u;
		++curLab;
		int h = 0;
		for(int v : adj[u]){
			if(v == p) continue;
			if(sz[v] > sz[h]) h = v;
		}
		if(h) hld(h, u);
		for(int v : adj[u]){
			if(v != h && v != p){
				++curChain;
				hld(v, u);
			}
		}
	}
	struct Node{
		int cnt1, cnt2;
		Node(int _cnt1 = 0, int _cnt2 = 0){
			cnt1 = _cnt1;
			cnt2 = _cnt2;
		}
		Node operator + (const Node &rhs) const{
			Node res;
			res.cnt1 = cnt1 + rhs.cnt1;
			res.cnt2 = cnt2 + rhs.cnt2;
			return res;
		}
	}it[maxN << 2];
	int lz[maxN << 2];
	void push(int id){
		if(lz[id] == 0) return;
		lz[id << 1] ^= 1;
		lz[id << 1 | 1] ^= 1;
		swap(it[id << 1].cnt1, it[id << 1].cnt2);
		swap(it[id << 1 | 1].cnt1, it[id << 1 | 1].cnt2);
		lz[id] = 0;
		return;
	}
	void build(int id, int l, int r){
		if(l == r){
			int u = arr[l];
			if(numLeaves[u] == 2) it[id].cnt2 = 1;
			else it[id].cnt1 = 1;
			return;
		}
		int mid = l + r >> 1;
		build(id << 1, l, mid);
		build(id << 1 | 1, mid + 1, r);
		it[id] = it[id << 1] + it[id << 1 | 1];
	}
	void update(int id, int l, int r, int u, int v){
		if(l > v || r < u) return;
		if(l >= u && r <= v){
			swap(it[id].cnt1, it[id].cnt2);
			lz[id] ^= 1;
			return;
		}
		push(id);
		int mid = l + r >> 1;
		update(id << 1, l, mid, u, v);
		update(id << 1 | 1, mid + 1, r, u, v);
		it[id] = it[id << 1] + it[id << 1 | 1];
	}
	Node get(int id, int l, int r, int u, int v){
		if(l >= u && r <= v) return it[id];
		int mid = l + r >> 1;
		push(id);
		if(v <= mid) return get(id << 1, l, mid, u, v);
		if(u > mid) return get(id << 1 | 1, mid + 1, r, u, v);
		Node L = get(id << 1, l, mid, u, v);
		Node R = get(id << 1 | 1, mid + 1, r, u, v);
		return L + R;
	}
	long long getNode(int u){
		Node answer;
		while(chain[u] != chain[1]){
			answer = answer + get(1, 1, n, lab[top[chain[u]]], lab[u]);
			u = par[top[chain[u]]];
		}
		if(u != 1) answer = answer + get(1, 1, n, lab[1] + 1, lab[u]);
		return answer.cnt1 + 2 * answer.cnt2;
	}
	void change(int u){
		while(chain[u] != chain[1]){
			update(1, 1, n, lab[top[chain[u]]], lab[u]);
			u = par[top[chain[u]]];
		}
		if(u != 1) update(1, 1, n, lab[1] + 1, lab[u]);
	}
	int deg[maxN];
	int cnt[maxN];
	bool Leaves[maxN];
	void solve(){
		dfs();
		hld();
		build(1, 1, n);
		FOR(i, 1, n)deg[i] = adj[i].size();
		int orgLeaves = 0;
		FOR(i, 1, n)if(deg[i] <= 1)++orgLeaves;
		FOR(i, 1, n)Leaves[i] = deg[i] <= 1;
//		cout << orgLeaves << '\n';
		FOR(i, 1, q){
			int curLeaves = orgLeaves;
			for(int u : query[i]){
				if(deg[u] <= 1)--curLeaves;
				++curLeaves;
				deg[u]++;
				cnt[u]++;
			}
			sort(all(query[i]));
			uni(query[i]);
			if(curLeaves % 2 == 1){
				cout << -1 << '\n';
				for(int u : query[i]){
					deg[u] = adj[u].size();
					cnt[u] = 0;
				}
				continue;
			}
			long long answer = rem;
			for(int u : query[i]){
				if(Leaves[u]){
					answer += cnt[u];
					if(cnt[u] % 2 == 0){
						answer -= getNode(u);
						change(u);
						answer += getNode(u);
					}
				}else{
					answer += cnt[u];
					if(cnt[u] % 2 == 1) {
						answer -= getNode(u);
						change(u);
						answer += getNode(u);
					}
				}

			}
			cout << answer << '\n';
			for(int u : query[i]){
				if(Leaves[u]){
//					answer += cnt[u];
					if(cnt[u] % 2 == 0)change(u);
				}else{
//					answer += cnt[u];
					if(cnt[u] % 2 == 1) change(u);
				}

			}
			for(int u : query[i]){
				deg[u] = adj[u].size();
				cnt[u] = 0;
			}
		}
	}
}
void process(){
	cin >> n >> q;
	FOR(i, 1, n - 1){
		int u, v;
		cin >> u >> v;
		adj[u].emplace_back(v);
		adj[v].emplace_back(u);
	}
	FOR(i, 1, q){
		cin >> numNode[i];
		query[i].resize(numNode[i]);
		for(int &u : query[i])cin >> u;
	}
	if(subtask2 :: check()) return subtask2 :: solve();
	return ac :: solve();

}
//#define LOVE "crt"
int main(){
//	freopen(LOVE".inp", "r", stdin);
//	freopen(LOVE".out", "w", stdout);
	ios_base :: sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	process();
	return 0;
}

/*
7 3
1 2
2 4
4 5
5 6
5 7
3 4
1 4
2 2 4
1 1

7 3
1 2
2 4
4 5
5 7
3 4
4 1 1 2 6
3 6 6 6 2
2 2 7
*/
#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...