【AtCoder】ABC 444 E - Sparse Range

E - Sparse Rangeatcoder.jp favicon

実行時間制限: 2 sec / メモリ制限: 1024 MiB / Difficulty: 1107 / NoviSteps: ??? / 配点: 450 点

問題概要

長さ NN の整数列 AA と正整数 DD が与えられるので、以下の条件をともに満たす整数の組 (L,R)(L,R) の個数を求めよ。

  • 1LRN1 \leq L \leq R \leq N
  • Li<jRL \leq i < j \leq R を満たす全ての整数の組 (i,j)(i,j) について、 AiAjD|A_i-A_j|\geq D である

制約

  • 1N2×1051 \leq N \leq 2 \times 10^5
  • 1Ai2×1051 \leq A_i \leq 2 \times 10^5
  • 入力される値は全て整数

考察

ある区間 [L,R][L, R] が条件を満たすとき、その部分区間([L+1,R][L+1, R] など)も条件を満たす。

したがって、尺取り法によって、LL を固定したときの条件を満たす最大の RR を求めることができる。


ここで、[L,R1][L, R-1] が条件を満たしているとして、右端を RR に進めるときに、条件を満たすかどうかを判定する必要がある。

愚直にやるなら、新たな要素 ARA_RAL,AL+1,,AR1A_L, A_{L+1}, \cdots, A_{R-1} と全て比較して、AiARD|A_i - A_R| \geq D であるかを確認すればよいが、これは O(N)O(N) の計算量がかかってしまう。

しかしよく考えると、AA がソートされていれば、追加する ARA_R に隣接する値のみを確認すればよいことが分かる。


理由 (クリックで展開)

昇順ソートされた数列 {A,B,C,E}\{\cdots A, B, C, E\cdots\} について、新たな数 X(B<X<C)X \: (B < X < C) を追加するとする。

このとき、XBDX - B \geq D ならば、当然 XADX - A \geq D も成り立つ。

右側についても同様で、CXDC - X \geq D ならば EXDE - X \geq D も成り立つ。


したがって、[L,R1][L, R-1] の要素をソートされた状態で管理し、ARA_R をキーとして二分探索を行い、以下の2つの条件を満たすかを確認すればよい。

  • ARA_R 以上の最小値 mRm_R について mRARDm_R - A_R \geq D である。
  • ARA_R 未満の最大値 mLm_L について ARmLDA_R - m_L \geq D である。

これはsetとそれに備わっているlower_boundメソッドを用いれば簡単に実装でき、計算量は O(NlogN)O(N \log N) となる。

実装例

CPP
1.#include <bits/stdc++.h>
2.using namespace std;
3.
4.#define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++)
5.
6.using ll = long long;
7.
8.// ======================================== //
9.
10.int main()
11.{
12. int N;
13. ll D;
14. cin >> N >> D;
15. vector<ll> A(N);
16. rep(i, 0, N) cin >> A[i];
17.
18. ll ans = 0;
19. set<ll> st;
20. int R = 0;
21. rep(L, 0, N)
22. {
23. while (R < N)
24. {
25. auto itr = st.lower_bound(A[R]);
26.
27. if (itr != st.end() && abs(*itr - A[R]) < D)
28. break;
29. if (itr != st.begin() && abs(*prev(itr) - A[R]) < D)
30. break;
31.
32. st.insert(A[R]);
33. R++;
34. }
35.
36. ans += R - L;
37.
38. st.erase(A[L]);
39. }
40.
41. cout << ans << endl;
42.
43. return 0;
44.}
atcoder.jp favicon

実装時間: 20分

コメント

尺取り法のいい練習問題だと思う。