Official

E - White Pawn Editorial by en_translator


Consider maintaining a set of squares (the indices of columns), updating incrementally for each row.
In other words, let \(S_i=\{ j\in\mathbb{Z} \mid \)the white pawn can reach \((i,j)\)\(\}\ (0\leq i \leq 2N)\), and we want to derive \(S_{i+1}\) from \(S_i\) for each \(i=0,1,\ldots 2N-1\).
Of course, if we do this naively, it will exceed the time limit.

Actually however, we can only focus on the difference between \(S_i\) and \(S_{i+1}\) to drastically improve the computation time. The key fact is:

  • Suppose that \((i+1, j)\) has no black pawn. If the white pawn is reachable to \((i, j)\), so is \((i+1 ,j)\); if it cannot reach \((i,j)\), then it cannot to \((i+1 ,j)\) either.

First, we can now see that \(S_i=S_{i-1}\) if the \(i\)-th row does not contain black pawns. Also, even for the row with black pawns, the between transitions from \(S_{i-1}\) to \(S_i\) are either:

  • If ( \(j-1 \in S_{i-1}\) or \(j+1 \in S_{i-1}\) ) and \(j \notin S_{i-1}\), then \(j \notin S_{i-1} \to j \in S_i\).
  • If ( \(j-1 \notin S_{i-1}\) and \(j+1 \notin S_{i-1}\) ) and \(j \in S_{i-1}\), then \(j \in S_{i-1} \to j \notin S_i\).

Moreover, since any \(j\) such that \(j<0\) or \(2N<j\) can never be given as an column index of a black pawn, and since \(j\notin S_0\), \(j\notin S_i\) for every \(i\), so we do not have to take care of the left and right boundary.

Therefore, only focusing on the squares with black pawns, it can be solved as follows. First, sort \((X_i, Y_i)\) in the increasing order. Next, starting from \(S=\{N\}\), for each chunk with the equal \(X_i\) in the sorted sequence, repeat the following. We assume \(X_l=X_{l+1}=\cdots =X_r\).

  • Prepare a set \(A\) that will eventually be added to \(S\) and a set \(B\) that will be removed from \(S\), both initialized with empty sets. For each \(i=l,l+1, \ldots, r\), perform the following operations:

    • If ( \(Y_i-1 \in S\) or \(Y_i+1 \in S\) ) and \(Y_i \notin S\), then add \(Y_i\) to \(A\).
    • If ( \(Y_i-1 \notin S\) and \(Y_i+1 \notin S\) ) and \(Y_i \in S\), then add \(_i\) to \(B\).
    • Otherwise, do nothing.
  • Update \(S\) by adding the elements of \(A\) to \(S\) and removing the elements of \(B\) from \(S\).

The final set \(S\) is a set of indices \(j\) such the white pawn is reachable to \((2N, j)\), and the desired answer is the size of the set \(\lvert S\rvert\).

The time complexity is \(O(M\log M)\) for the initial sort, \(O(\log M)\) for each lookup, addition, and removal if an ordered “set” is used, so \(O(M\log M)\) in total. Therefore, the problem can be solved in \(O(M\log M)\) time, which is fast enough. Also, by the facts so far, if the white pawn is reachable to \((2N,j)\) then \(j = N\) or the row \(j\) has at least one black pawn, so the answer is at most \(M+1\), which fits in a \(32\)-bit integer.

Sample code in C++:

#include <bits/stdc++.h>

using namespace std;

int main(void) {
	int n, m;
	vector<pair<int, int> > p;
	vector<int>a, b;
	set<int>s;
	int x, y;
	int l, r;
	cin >> n >> m;
	for (int i = 0; i < m; i++) {
		cin >> x >> y;
		p.push_back({ x,y });
	}
	sort(p.begin(), p.end());
	s.insert(n);
	l = 0;
	while (l < m) {
		a.clear();
		b.clear();
		r = l;
		while (r < m) {
			if (p[r].first == p[l].first)r++;
			else break;
		}
		for (int i = l; i < r; i++) {
			y = p[i].second;
			if (((s.find(y - 1) != s.end()) || (s.find(y + 1) != s.end())) && (s.find(y) == s.end()))a.push_back(y);
			if (((s.find(y - 1) == s.end()) && (s.find(y + 1) == s.end())) && (s.find(y) != s.end()))b.push_back(y);
		}
		for (int i = 0; i < a.size(); i++)s.insert(a[i]);
		for (int i = 0; i < b.size(); i++)s.erase(b[i]);
		l = r;
	}
	cout << s.size() << endl;
}

posted:
last update: