Submission #815127

#TimeUsernameProblemLanguageResultExecution timeMemory
815127WonderfulWhaleJail (JOI22_jail)C++17
100 / 100
3523 ms308640 KiB
//#pragma GCC optimize("O3,unroll-loops")
#include <bits/stdc++.h>
using namespace std;
 
#define pii pair<int, int>
#define st first
#define nd second
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()
 
int Gg = 0;
int col[120009];

bool dfs2(int x);
 
struct SegTree {
	int T=1;
	vector<unordered_set<int>> t;
	void build(int n) {
		T=1;
		while(T<=n) T*=2;
		t.resize(2*T);
		for(int i=0;i<2*T;i++) t[i].clear();
	}
	bool help(int x, int s) {
		while(sz(t[x])) {
			auto it = t[x].begin();
			if(*it==s) {
				//cerr << "tutaj\n";
				if(sz(t[x])==1) break;
				it++;
			}
			int y = *it;
			//cout << s << " -> " << y << "\n";
			if(col[y]==1) return false;
			if(col[y]==0&&!dfs2(y)) return false;
		}
		return true;
	}
	bool query(int l, int r, int s) {
		//cout << "query: " << l << " " << r << "\n";
		l+=T, r+=T;
		if(!help(l, s)) return false;
		if(l!=r&&!help(r, s)) return false;
		while(l/2!=r/2) {
			if(l%2==0&&!help(l+1, s)) return false;
			if(r%2==1&&!help(r-1, s)) return false;
			l/=2;
			r/=2;
		}
		return true;
	}
	void add(int x, int val) {
		x+=T;
		while(x) {
			t[x].insert(val);
			x/=2;
		}
	}
	void remove(int x, int val) {
		x+=T;
		while(x) {
			t[x].erase(val);
			x/=2;
		}
	}
};
struct SegTree2 {
	int T = 1;
	vector<unordered_set<int>> t;
	void build(int n) {
		T=1;
		while(T<=n) T*=2;
		t.resize(2*T);
		for(int i=0;i<2*T;i++) t[i].clear();
	}
	void add(int l, int r, int val) {
		//cout << "add: "<< l << " " << r << " " << val << "\n";
		l+=T, r+=T;
		t[l].insert(val);
		if(l!=r) t[r].insert(val);
		while(l/2!=r/2) {
			if(l%2==0) t[l+1].insert(val);
			if(r%2==1) t[r-1].insert(val);
			l/=2;
			r/=2;
		}
	}
	void remove(int l, int r, int val) {
		//cout << "remove: "<< l << " " << r << " " << val << "\n";
		l+=T, r+=T;
		t[l].erase(val);
		if(l!=r) t[r].erase(val);
		while(l/2!=r/2) {
			if(l%2==0) t[l+1].erase(val);
			if(r%2==1) t[r-1].erase(val);
			l/=2;
			r/=2;
		}
	}
	bool help(int x, int s) {
		while(sz(t[x])) {
			//cerr << "tutaj2\n";
			auto it = t[x].begin();
			if(*it==s) {
				if(sz(t[x])==1) break;
				it++;
			}
			int y = *it;
			//cout << s << " -> " << y << "\n";
			//cout << s << " " << y << " " << col[y] << "\n";
			if(col[y]==1) return false;
			if(col[y]==0&&!dfs2(y)) return false;
		}
		return true;
	}
	bool query(int x, int s) {
		//cout << "zaczynamy!!!\n";
		x+=T;
		while(x) {
			if(!help(x, s)) return false;
			x/=2;
		}
		return true;
	}
};
 
vector<int> G[120009];
vector<int> G2[120009];
int tin[120009], tout[120009], T;
int jp2[120009][20];
int deg[120009];
pii tab[120009];
int dep[120009];
int p[120009];
int heavy[120009];
int pos[120009], P;
int head[120009];
 
 
int dfs(int x, int y) {
	p[x] = y;
	dep[x] = dep[y]+1;
	int sz = 1, max_sz=0;
	tin[x] = ++T;
	jp2[x][0] = y;
	for(int i=1;i<20;i++) jp2[x][i] = jp2[jp2[x][i-1]][i-1];
	for(int z:G[x]) if(z!=y) {
		int c_sz = dfs(z, x);
		sz += c_sz;
		if(c_sz>max_sz) {
			max_sz = c_sz;
			heavy[x] = z;
		} 
	}
	tout[x] = ++T;
	return sz;
}
 
void decompose(int x, int h) {
	head[x] = h;
	pos[x] = ++P;
	if(heavy[x]) {
		decompose(heavy[x], h);
	}
	for(int y:G[x]) {
		if(y!=p[x]&&y!=heavy[x]) decompose(y, y);
	}
}
 
bool is_ancestor(int x, int y) {
	return tin[x]<=tin[y]&&tout[x]>=tout[y];
}
 
int lca(int x, int y) {
	if(is_ancestor(x, y)) return x;
	if(is_ancestor(y, x)) return y;
	for(int i=19;i>=0;i--) {
		if(!is_ancestor(jp2[x][i], y)) {
			x = jp2[x][i];
		}
	}
	return jp2[x][0];
}
 
bool is_on_path(int x, int a, int b) {
	return is_ancestor(a, x)&&is_ancestor(x, b);
}
 
bool f(int x, int a, int b) {
	int y = lca(a, b);
	//cerr << "lca: " << a << " " << b << " " << y << "\n";
	//cerr << "checking: " << x << " " << a << " " << b << " " << (is_on_path(x, y, a)||is_on_path(x, y, b)) << "\n";
	return is_on_path(x, y, a)||is_on_path(x, y, b);
}
 
SegTree seg1;
SegTree2 seg2;
 
bool hld_query(int a, int b, int s) {
	//cout << "hld_query: " << a << " " << b << "\n";
	vector<int> ret;
	for (; head[a] != head[b]; b=p[head[b]]) {
		if (dep[head[a]] > dep[head[b]]) swap(a, b);
		if(!seg1.query(pos[head[b]], pos[b], s)) return false;
	}
	if (dep[a] > dep[b]) swap(a, b);
	if(!seg1.query(pos[a], pos[b], s)) return false;
	return true;
}
 
void hld_add(int a, int b, int val) {
	//cout << "hld_query: " << a << " " << b << "\n";
	vector<int> ret;
	for (; head[a] != head[b]; b=p[head[b]]) {
		if (dep[head[a]] > dep[head[b]]) swap(a, b);
		seg2.add(pos[head[b]], pos[b], val);
	}
	if (dep[a] > dep[b]) swap(a, b);
	seg2.add(pos[a], pos[b], val);
}
 
void hld_remove(int a, int b, int val) {
	//cout << "hld_query: " << a << " " << b << "\n";
	vector<int> ret;
	for (; head[a] != head[b]; b=p[head[b]]) {
		if (dep[head[a]] > dep[head[b]]) swap(a, b);
		seg2.remove(pos[head[b]], pos[b], val);
	}
	if (dep[a] > dep[b]) swap(a, b);
	seg2.remove(pos[a], pos[b], val);
}
 
int N;
 
bool dfs2(int x) {
	assert(col[x]==0);
	col[x] = 1;
	//cout << "dfs: " << x << "\n";
	if(!hld_query(tab[x].st, tab[x].nd, x)) return false;
	if(!seg2.query(pos[tab[x].nd], x)) return false;
	col[x] = 2;
	seg1.remove(pos[tab[x].st], x);
	//cout << "removing: " << x << "\n";
	hld_remove(tab[x].st, tab[x].nd, x);
	return true;
}
 
int32_t main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
 
	int q=1;
	cin >> q;
	while(q--) {
		int n, m;
		cin >> n;
		N = n;
		Gg=0;
		for(int i=1;i<=n;i++) {
			G[i].clear();
			head[i] = 0;
			heavy[i] = 0;
			dep[i] = 0;
			p[i] = 0;
		}
		for(int i=0;i<n-1;i++) {
			int a, b;
			cin >> a >> b;
			G[a].pb(b);
			G[b].pb(a);
		}
		tin[0] = T = 0;
		dfs(1, 0);
		P = 0;
		decompose(1, 1);
		tout[0] = T;
		cin >> m;
		for(int i=0;i<m;i++) {
			G2[i].clear();
			deg[i] = 0;
			col[i] = 0;
		}
		seg1.build(n+9);
		seg2.build(n+9);
		for(int i=0;i<m;i++) {
			cin >> tab[i].st >> tab[i].nd;
			seg1.add(pos[tab[i].st], i);
			hld_add(tab[i].st, tab[i].nd, i);
		}
		bool ans = true;
		for(int i=0;i<m;i++) {
			if(!ans) continue;
			if(!col[i]) {
				ans&=dfs2(i);
			}
		}
		if(ans) {
			cout << "Yes\n";
		} else {
			cout << "No\n";
		}
	}
}
#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...