이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#include <bits/stdc++.h>
namespace std {
template<class Fun>
class y_combinator_result {
	Fun fun_;
public:
	template<class T>
	explicit y_combinator_result(T &&fun): fun_(std::forward<T>(fun)) {}
	template<class ...Args>
	decltype(auto) operator()(Args &&...args) {
		return fun_(std::ref(*this), std::forward<Args>(args)...);
	}
};
template<class Fun>
decltype(auto) y_combinator(Fun &&fun) {
	return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun));
}
} // namespace std
struct rollback_union_find {
	std::vector<int> par;
	std::stack<std::pair<int, int>> stk;
	rollback_union_find(int n) {
		par.resize(n);
		iota(par.begin(), par.end(), 0);
	}
	int leader(int u) {
		if (u == par[u])
			return u;
		stk.emplace(u, par[u]);
		return par[u] = leader(par[u]);
	}
	void merge(int u, int v) {
		u = leader(u), v = leader(v);
		if (u == v)
			return;
		stk.emplace(v, v);
		par[v] = u;
	}
	bool same(int u, int v) { return leader(u) == leader(v); }
	int version() { return (int)stk.size(); }
	void rollback(int ver) {
		while ((int)stk.size() > ver) {
			par[stk.top().first] = stk.top().second;
			stk.pop();
		}
	}
};
int main() {
	using namespace std;
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	int N, M, Q;
	cin >> N >> M >> Q;
	vector<pair<int, int>> E(M);
	for (auto &[u, v] : E) {
		cin >> u >> v;
		u--, v--;
	}
	int max_l = 0;
	vector<pair<int, int>> Z(Q);
	for (auto &[l, r] : Z) {
		cin >> l >> r;
		l--, r--;
		max_l = max(max_l, l);
	}
	vector<int> ans(M, -1);
	rollback_union_find dsu(2 * N);
	y_combinator([&](auto self, int ql, int qr, int al, int ar) -> void {
		if (qr < ql)
			return;
		if (al == ar) {
			for (int i = ql; i <= qr; i++)
				ans[i] = al;
			return;
		}
		int qm = (ql + qr) / 2, ver = dsu.version();
		for (int i = ql; i < qm; i++) {
			dsu.merge(E[i].first, E[i].second + N);
			dsu.merge(E[i].first + N, E[i].second);
			if (dsu.same(E[i].first, E[i].first + N) || 
				dsu.same(E[i].second, E[i].second + N)) {
				ans[qm] = M;
				break;
			}
		}
		if (ans[qm] == -1) {
			for (int i = ar; i >= al; i--) {
				if (i == M)
					continue;
				dsu.merge(E[i].first, E[i].second + N);
				dsu.merge(E[i].first + N, E[i].second);
				if (dsu.same(E[i].first, E[i].first + N) || 
					dsu.same(E[i].second, E[i].second + N)) {
					ans[qm] = i;
					break;
				}
			}
			if (ans[qm] == -1)
				ans[qm] = qm;
		}
		dsu.rollback(ver);
		bool b = false;
		for (int i = ar; i > ans[qm]; i--) {
			if (i == M)
				continue;
			dsu.merge(E[i].first, E[i].second + N);
			dsu.merge(E[i].first + N, E[i].second);
			if (dsu.same(E[i].first, E[i].first + N) || 
				dsu.same(E[i].second, E[i].second + N)) {
				b = true;
				break;
			}
		}
		if (b) {
			for (int i = ql; i <= qm; i++)
				ans[i] = ans[qm];
		} else {
			self(ql, qm - 1, al, ans[qm]);
		}
		dsu.rollback(ver);
		b = false;
		for (int i = ql; i <= qm; i++) {
			dsu.merge(E[i].first, E[i].second + N);
			dsu.merge(E[i].first + N, E[i].second);	
			if (dsu.same(E[i].first, E[i].first + N) || 
				dsu.same(E[i].second, E[i].second + N)) {
				b = true;
				break;
			}
		}
		if (b) {
			for (int i = qm + 1; i <= qr; i++)
				ans[i] = M;
		} else {
			self(qm + 1, qr, ans[qm], ar);
		}
		dsu.rollback(ver);
	})(0, max_l, 0, M);
	for (auto [l, r] : Z) 
		cout << (r < ans[l] ? "YES\n" : "NO\n");
}
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... |