公式

C - ペアの合計点 / Total Score of Pairs 解説 by kyopro_friends


この問題は二分探索や尺取法を用いて解くことができます。

\(A\) はソートされているとしてよいです。

\(i\) を固定したとき、条件を満たす \(j\) がいくつあるかを考えます。
\(A\) はソート済みなので、ある \(j\) が条件を満たせばそれより大きなindexは全て条件を満たします。よって「\(A_j\geq K-A_i\) を満たす最小の \(j>i\) は?」を二分探索により求めることで条件を満たす \(j\) の個数がわかります。
二分探索 \(1\) 回あたり \(O(\log N)\) 時間なので、これを \(N\) 回行い全体で \(O(N\log N)\) 時間で求めることができます。

実装例 (C++)

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

int main(){
  int n, k;
  cin >> n >> k;
  vector<int>a(n);
  for(int i=0; i<n; i++) cin >> a[i];
  sort(a.begin(), a.end());

  long long ans = 0;
  for(int i=0; i<n; i++){
    int idx = lower_bound(a.begin(), a.end(), k-a[i]) - a.begin();
    ans += n - max(i+1, idx);
  }
  cout << ans << endl;
}

実装例 (Python)

from bisect import bisect_left
N, K = map(int, input().split())
A = list(map(int, input().split()))
A.sort()

ans = 0
for i, a in enumerate(A):
  ans += N - bisect_left(A, K-a, i+1)

print(ans)