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';
}
投稿日時:
最終更新: