公式

D - Make Target 2 解説 by cn449


\(\max(|x|, |y|)\) という式を簡潔に扱うために、\(|x| > |y|\) であるものと \(|x| \leq |y|\) であるものに場合分けして数え上げ、最後に足し合わせることで答えを求めます。

以下、\(|x| > |y|\) であるものの数え上げ方の一例を紹介します。\(|x| \leq |y|\) であるものの個数も同様に計算できます。

\(|x| > |y|\) であるとき、\(\max(|x|, |y|) = |x|\) です。したがって、\(x\)\(L \leq x \leq R\) かつ \(x\) が偶数である範囲で全探索し、\(|x| > |y|\) かつ \(D \leq y \leq U\) である \(y\) の個数を各 \(x\) について求めればよいです。\(|x| > |y|\)\(-|x| < y < |x|\) と同値であるため、\(x\) が固定されているとき集計対象となっている \(y\) の範囲は \(\max(-|x| + 1, D) \leq y \leq \min(|x| - 1, U)\) です。この範囲にある整数 \(y\) の個数は \(\max(0, \min(|x| - 1, U) - \max(-|x| + 1, D) + 1)\) 個であり、各 \(x\) に対して \(O(1)\) 時間で計算できます。したがって、\(|x| > |y|\) であるものの個数は \(X = R - L\) として \(O(X)\) 時間で計算できます。

実装例

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

int main() {
	int l, r, d, u;
	cin >> l >> r >> d >> u;
	ll ans = 0;

	// |x| > |y|
	for (int x = l; x <= r; x++) {
		if (x % 2 == 0) {
			int D = max(d, -abs(x) + 1);
			int U = min(u, abs(x) - 1);
			int C = U - D + 1;
			ans += max(C, 0);
		}
	}

	// |x| <= |y|
	for (int y = d; y <= u; y++) {
		if (y % 2 == 0) {
			int L = max(l, -abs(y));
			int R = min(r, abs(y));
			int C = R - L + 1;
			ans += max(C, 0);
		}
	}

	cout << ans << '\n';
}

投稿日時:
最終更新: