제출 #1312630

#제출 시각아이디문제언어결과실행 시간메모리
1312630vlomaczkJoker (BOI20_joker)C++20
0 / 100
1 ms1284 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
using namespace __gnu_pbds;
using namespace std;

template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

struct Bipartite {
	bool bipartite = 1;
	ll m;
	vector<pair<ll, ll>> e;
	vector<ll> rep, sajz, color;
	vector<bool> ans_r;
	vector<pair<ll, ll>> rep_r, sajz_r, g_r;
	vector<vector<pair<ll, ll>>> color_r;
	vector<set<ll>> g;
	ll size = 0;

	ll capture() { return size; } 

	Bipartite(vector<pair<ll, ll>> edges, ll n) {
		e = edges;
		m = e.size();
		rep.assign(n+1, 0);
		for(ll i=1; i<=n; ++i) rep[i] = i;
		sajz.assign(n+1, 1);
		color.assign(n+1, 1);
		g.resize(n+1);
	}

	ll Find(ll v) {
		return (rep[v]==v ? v : Find(rep[v]));
	}

	void dfs(ll v, ll p) {
		color_r.back().push_back({v,color[v]});
		color[v] = 1 - color[v];
		for(auto u : g[v]) if(u!=p) dfs(u,v);
	}

	void add(ll i) {
		size++;
		ans_r.push_back(bipartite);
		rep_r.push_back({});
		sajz_r.push_back({});
		color_r.push_back({});
		g_r.push_back({});
		auto[a,b] = e[i];
		if(Find(a)==Find(b)) {
			if(color[a]==color[b]) {
				bipartite = 0;
			}
		} else {
			if(sajz[Find(b)] > sajz[Find(a)]) swap(a,b);
			if(color[a]==color[b]) dfs(a,a);
			g[a].insert(b);
			g[b].insert(a);
			g_r.back() = {a, b};
			a = Find(a);
			b = Find(b);
			sajz_r.back() = {a,sajz[a]};
			rep_r.back() = {b,rep[b]};
			sajz[a] += sajz[b];
			rep[b] = a;
		}
	}

	void rollback() {
		assert(ans_r.size());
		size--;
		bipartite = ans_r.back(); ans_r.pop_back();
		auto[a,b] = rep_r.back(); rep[a] = b; rep_r.pop_back();
		auto[c,d] = sajz_r.back(); sajz[c] = d; sajz_r.pop_back();
		auto[x,y] = g_r.back();
		g[x].erase(y); g[y].erase(x);
		g_r.pop_back();
		for(auto[k,l] : color_r.back()) color[k] = l;
		color_r.pop_back();
	}
};

vector<pair<ll, ll>> edges;
vector<ll> last;

void cdq(ll l1, ll r1, ll l2, ll r2, Bipartite &bp) { // We use divide & conquer cause i < j => last[i] <= last[j]
	if(l1>r1) return;
	ll m = (l1+r1) / 2;
	ll size1 = bp.capture();
	for(ll i=l1; i<m; ++i) bp.add(i);
	last[m] = r2;
	ll size2 = bp.capture();
	while(bp.bipartite && last[m] >= l2) {
		bp.add(last[m]);
		last[m]--;
	}
	while(bp.size > size2) bp.rollback();
	bp.add(m);
	cdq(m+1, r1, last[m], r2, bp);
	while(bp.size > size1) bp.rollback();
	for(ll i=m; i<=r1; ++i) bp.add(i);
	cdq(l1,m-1,l2,last[m],bp);
}

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);

	ll n,m,q;
	cin >> n >> m >> q;
	edges.resize(m);
	last.resize(m);
	for(ll i=0; i<m; ++i) {
		cin >> edges[i].first >> edges[i].second;
	}
	Bipartite bp(edges, n);
	cdq(0,m-1,0,m-1,bp);
	while(q--) {
		ll l, r;
		cin >> l >> r;
		--l; --r;
		if(r <= last[l]) cout << "YES\n";
		else cout << "NO\n";
	}

	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...