lower_bound() 系の教育的問題
問題概要
一直線上に 個の点がある。点 の座標は である。
この直線上で幅 の区間を配置する。左端の座標を とするとき、 を満たす の個数をスコアとする。最大スコアを求めよ。
制約
考えたこと
まず重要な考察として
幅 の区間を置くとき、その左端がある点に一致する場合のみを考えればよい
というのがある。なぜなら、そうでない場合を考えたとき、区間を右へと移動させても、区間の覆う点が減少することはないからだ (むしろ増えるかもしれない)。そして、右側に移動していって、左端に点が重なる瞬間まで右側に移動できる。
以上の考察から、区間の左端が点に一致する場合のみ考えれば良い。
各点に対して
簡単のため、 をソートしよう。このとき、問題は次のようになる。
各 に対して、
を満たすような の個数を求めよ (その最大値が答えとなる)。
これは、次の手順で求められる。
- となる最小の を求める (
lower_bound()
によって、計算量 で求められる) - が答え
全体の計算量は となる。
コード
#include <bits/stdc++.h> using namespace std; int main() { long long N, M; cin >> N >> M; vector<long long> A(N); for (int i = 0; i < N; ++i) cin >> A[i]; sort(A.begin(), A.end()); int res = 0; for (int i = 0; i < N; ++i) { long long x = A[i]; int it = lower_bound(A.begin(), A.end(), x + M) - A.begin(); res = max(res, it - i); } cout << res << endl; }