Official

E - ペアの選定 / Choosing Pairs Editorial by sounansya Editorial for printing


\(i<j\) という制約を無くして考え、求まった答えに \(i=j\) を満たす個数を引き \(2\) で割ることで答えを求めます。

まず、部員を技術力の昇順にソートします。すると、部員 \(j\) を固定した際に「選んだ \(2\) 人の技術力の合計が \(X\) 以上」という条件を満たす部員はある部員から部員 \(N\) までの番号が連続した何人かになります。したがって、各 \(j\) に対し \(A_i \geq X-A_j\) を満たす最小の \(i\) を \(c_j\) とすると、\(j=1,2,\ldots,N\) に対し部員 \(c_j\) から部員 \(N\) の中で体力が \(Y-B_j\) 以上の人を求められればこの問題に正解できることが分かります。

\(c_j\) の値は二分探索や尺取り法などで計算することができます。また、\(A\) の単調性より \(c_j\) の値は広義単調減少となります。

したがって、以下のようなアルゴリズムで本問題の答えを求めることができます:

  • \(\text{ans}=0\) とし、\(S\) を空な多重集合とする。
  • \(j=1,2,\ldots,N\) に対して以下を行う:
    • \(k=c_j,\ldots,c_{j-1}-1\) に対し、\(S\) に \(B_k\) を追加する。ただし、\(c_0=N+1\) とする。
    • \(\text{ans}\) に \(S\) の中で \(Y-B_j\) 以上の要素の個数を加算する。
  • \(\text{ans}\) が求める答えである。

\(c\) の単調性より \(S\) に対する要素の削除が発生しないことを利用しています。

あとは \(S\) の中で \(Y-B_j\) 以上の要素の個数を求められれば良いですが、これは \(B_i,Y-B_i\) の値をまとめて座標圧縮した値を用いることにより Fenwick Tree などを用いることで計算することができます(\(Y-B_i\) の値は入れなくても良いですが、入れた方が考えることが少なくなると思います)。

また、座標圧縮しないでも Wavelet Matrix などを用いるとより実装が簡潔になります。

以上を適切に実装することでこの問題に正答することができます。計算量は \(O(N \log N)\) です。

実装例(Python3)

from bisect import bisect_left
from atcoder.fenwicktree import FenwickTree

n, x, y = map(int, input().split())
ab = sorted(tuple(map(int, input().split())) for _ in range(n))
bb = sorted(set(b for a, b in ab))
fw = FenwickTree(len(bb))
c = n - 1
ans = 0
for a, b in ab:
    while c >= 0 and ab[c][0] + a >= x:
        fw.add(bisect_left(bb, ab[c][1]), 1)
        c -= 1
    ans += fw.sum(bisect_left(bb, y - b), len(bb))
    ans -= 2 * a >= x and 2 * b >= y
print(ans // 2)

posted:
last update: