Submission #291899

#TimeUsernameProblemLanguageResultExecution timeMemory
291899BertedJoker (BOI20_joker)C++14
100 / 100
405 ms18668 KiB
#include <iostream>
#include <vector>
#include <algorithm>
#include <assert.h>
#define vi vector<int>
#define pii pair<int, int>
#define fst first
#define vpi vector<pii>
#define ppi pair<pii, int>
#define snd second

using namespace std;

/*
	Idea : 
	Define R_i as the right-most index such that Query(i .. R[i]) = "YES"
	Observe that R[i - 1] <= R[i] for all i
	Therefore, we can do DnC
	:D 
*/

int n, m, q;

pii edge[200001];
int ans[200001], sz[200001];
pair<int, bool> par[200001];

pair<int, bool> fn(int u)
{
	if (u == par[u].fst) return par[u];
	else
	{
		pair<int, bool> ret = fn(par[u].fst);
		ret.snd ^= par[u].snd;
		return ret;
	}
}

inline bool jn(int a, int b, vpi& rb)
{
	pair<int, bool> parA = fn(a), parB = fn(b);
	// cout << "JOIN " << a << " - " << b << " " << parA.snd << " " << parB.snd << " , " << parA.fst << " - " << parB.fst << "\n";
	if (parA.fst != parB.fst)
	{
		if (sz[parA.fst] < sz[parB.fst]) {swap(parA, parB);}
		rb.push_back({parB.fst, sz[parB.fst]});
		sz[parA.fst] += sz[parB.fst];
		par[parB.fst] = {parA.fst, parA.snd == parB.snd};
		return 1;
	}
	return parA.snd != parB.snd;
}

inline void rollbackOp(vpi& rb)
{
	for (int i = rb.size() - 1; i >= 0; i--)
	{
		sz[par[rb[i].fst].fst] -= rb[i].snd;
		par[rb[i].fst] = {rb[i].fst, 0};
	}
	rb.clear();
}

void solve(int L, int R, int lb, int ub)
{
	if (L <= R)
	{
		int M = L + R >> 1; int early = ub + 1; vpi rbVec;
		// cout << "SOLVE " << L << " " << R << " " << M << " " << lb << " " << ub << "\n";
		for (int i = L; i < M; i++)
		{
			if (jn(edge[i].fst, edge[i].snd, rbVec) == 0) {early = i; break;}
		}
		if (early > ub)
		{
			for (int i = ub; i >= max(M, lb); i--)
			{
				if (jn(edge[i].fst, edge[i].snd, rbVec) == 0) {early = i; break;}
			}
		}
		rollbackOp(rbVec);
		if (early < M)
		{
			for (int i = early + 1; i <= R; i++) 
			{
				ans[i] = m;
				// cout << i << " -> " << ans[i] << "\n";
			}
			solve(L, early, lb, ub);
		}
		else if (early > ub)
		{
			for (int i = L; i <= R; i++) {ans[i] = i - 1;}
		}
		else
		{
			ans[M] = early - 1;
			// cout << M << " -> " << ans[M] << "\n";

			for (int i = ub; i > early; i--) {jn(edge[i].fst, edge[i].snd, rbVec);}
			solve(L, M - 1, lb, early);
			rollbackOp(rbVec);

			bool b = 1;
			for (int i = L; i <= M; i++) {b &= jn(edge[i].fst, edge[i].snd, rbVec);}
			if (b) solve(M + 1, R, early, ub);
			else for (int i = M + 1; i <= R; i++) {ans[i] = m;}
			rollbackOp(rbVec);
		}	
	}
}

int main()
{
	ios :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin >> n >> m >> q;
	for (int i = 0; i < n; i++) {par[i] = {i, 0}; sz[i] = 1;}
	for (int i = 0; i < m; i++)
	{
		int u, v; cin >> u >> v;
		edge[i] = {u - 1, v - 1};
	}
	solve(0, m - 1, 0, m - 1);
	for (int i = 0; i < q; i++)
	{
		int l, r; cin >> l >> r; l--; r--;
		if (r > ans[l]) {cout << "NO\n";}
		else {cout << "YES\n";}
	}
	return 0;
}

Compilation message (stderr)

Joker.cpp: In function 'void solve(int, int, int, int)':
Joker.cpp:68:13: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   68 |   int M = L + R >> 1; int early = ub + 1; vpi rbVec;
      |           ~~^~~
#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...