B - 数の差がKのペア / Pairs with Difference K 解説 by admin
GPT 5.2 High概要
数列から異なる 2 要素を選び、差の絶対値がちょうど \(K\) になるペア数を、重複要素も考慮して高速に数えます。
考察
素朴に全てのペア \((i, j)\)(\(i<j\))を調べると、組み合わせ数は \(\frac{N(N-1)}{2}\) なので最大で約 \(2\times 10^5\) に対して \(O(N^2)\) となり、確実に時間切れになります。
ここで重要な観察は次の通りです:
- 「差の絶対値が \(K\)」とは、値の組としては \((x, x+K)\) の形を数えれば十分です。
なぜなら、\(|a-b|=K\) となるのは \(a=b+K\) または \(b=a+K\) のどちらかで、結局「小さい方を \(x\)、大きい方を \(x+K\)」と一意に定まるからです。 - 同じ値が複数回出てくるので、個数(頻度)を使うとまとめて数えられます。
例えば \(x\) が \(c\) 回、\(x+K\) が \(d\) 回出るなら、差が \(K\) になるペアは \(c \times d\) 個あります(それぞれの出現位置の組み合わせ)。
具体例:\(A=[1,1,4,4,4]\), \(K=3\)
- \(1\) は 2 回、\(4\) は 3 回なので、\((1,4)\) のペアは \(2\times 3=6\) 個。
この方針なら、各値 \(x\) について「\(x+K\) が何個あるか」を高速に取得できればよく、ハッシュ(辞書)で頻度管理すれば \(O(N)\) 近くで解けます。
アルゴリズム
- 数列 \(A\) の各値の出現回数を
Counter(辞書)で数える。cnt[v] = v の個数。 - 答え
ans=0を用意する。 cntに含まれる各値 \(x\) について、- \(x\) の個数を \(c\) とし、\(x+K\) の個数を \(d = \text{cnt}[x+K]\)(なければ 0)とする。
ans += c * dを加算する。
ansを出力する。
この数え方では常に「小さい方 \(x\) と大きい方 \(x+K\)」だけを数えるため、同じペアを 2 回数えることがありません(\((x, x+K)\) と \((x+K, x)\) を別扱いしないという条件を自然に満たします)。
計算量
- 時間計算量: \(O(N)\)(Counter 構築が \(O(N)\)、異なる値の種類数を \(M\) とするとループは \(O(M)\) で \(M \le N\))
- 空間計算量: \(O(M)\)(値の種類数ぶんの頻度を保持)
実装のポイント
頻度管理には
collections.Counterが便利です。cnt.get(x + K, 0)のように書くことで、存在しないキーでも 0 を返せて安全です。ansは最大で \(O(N^2)\) 規模になり得ますが、Python の整数はオーバーフローしないのでそのままで問題ありません。ソースコード
import sys
from collections import Counter
def main():
input = sys.stdin.readline
N, K = map(int, input().split())
A = list(map(int, input().split()))
cnt = Counter(A)
ans = 0
for x, c in cnt.items():
ans += c * cnt.get(x + K, 0)
print(ans)
if __name__ == "__main__":
main()
この解説は gpt-5.2-high によって生成されました。
投稿日時:
最終更新: