公式

D - Forbidden List 2 解説 by en_translator


Observations

Since the order of \(A\) does not affect the answer, we sort it in ascending order to assume \(A_1 < A_2 < \dots < A_N\). For convenience, we define sentinels as \(A_0 = -\infty, A_{N+1} = +\infty\).

First, we find the minimum value of \(A\) that is greater than or equal to \(X\) using binary search. Let \(A_s\) be this value.

When an integer is greater than or equal to \(X\) and not contained in \(A\), we simply call it a good integer.

For \(s \leq t \leq N+1\), there are \((A_t - x + 1)\) integers between \(X\) and \(A_t\) (inclusive), and \((t - s + 1)\) of them are contained in \(A\). Thus, the number of integers between \(X\) and \(A_t\) (inclusive) that are not contained in \(A\) is \((A_t - x + 1) - (t - s + 1)\). This is weakly monotonically increasing with respect to \(t\), so one can use binary search to find \(t_{r}\) such that:

  • \((A_{t_r - 1} - x + 1) - ((t_r - 1) - s + 1) < Y\),
  • \((A_{t_r - 0} - x + 1) - ((t_r - 0) - s + 1) \geq Y\).

For this \(t_r\), there are strictly less than \(Y\) good integers not exceeding \(A_{t_{r} - 1}\), and \(Y\) or more good integers not exceeding \(A_{t_r - 0}\), so the answer is between \(A_{t_{r} - 1}\) and \(A_{t_r - 0}\), exclusive. If we denote the answer by \(x_{ans}\), there are \((t_r - s)\) integers between \(X\) and \(x_{ans}\) (inclusive) that are contained in \(A\), so the answer is \(x_{ans} = X + (Y-1) + (t_r - s)\).

Sample code (C++)

#include <iostream>
using std::cin;
using std::cout;
#include <vector>
using std::vector;
#include <algorithm>
using std::sort;
using std::lower_bound;

typedef long long int ll;

ll n, q;
vector<ll> a;

void solve () {
	sort(a.begin(), a.end());
	for (ll qi = 0; qi < q; qi++) {
		ll x, y;
		cin >> x >> y;

		// a[0, si) < x && a[si, n) >= x
		ll si = lower_bound(a.begin(), a.end(), x) - a.begin();

		// youngest ti where |{x, x+1, ..., a[ti]} - {a[si], a[si+1], ..., a[ti]}| >= y
		ll ti;
		{
			ll ok = n, ng = si-1;
			while (ng + 1 < ok) {
				ll med = (ok + ng) / 2;
				if ((a[med] - x + 1) - (med - si + 1) >= y) {
					ok = med;
				} else {
					ng = med;
				}
			}
			ti = ok;
		}

		ll ans = x + (y-1) + (ti - si + 0);

		cout << ans << "\n";
	}
}

int main (void) {
	std::cin.tie(nullptr);
	std::ios_base::sync_with_stdio(false);
	
	cin >> n >> q;
	a.resize(n);
	for (ll i = 0; i < n; i++) {
		cin >> a[i];
	}

	solve();

	return 0;
}

投稿日時:
最終更新: