キーワード
数式処理,累積和,二分探索
解説
愚直に組 (i,j) を全探索しようとすると,計算量は O(NM) となり間に合いません。
考察をして計算量を改善する必要があります。
A の要素の順番は答えに影響しないので,A を昇順にソートして単調性を持たせます。
答えに Bk が寄与する部分は,∑i=1N∣Ai−Bk∣ です。
もし,Aj<Bk≤Aj+1 となる j が存在するならば,
∑i=1N∣Ai−Bk∣
=∑i=1j(Bk−Ai)+∑i=j+1N(Ai−Bk)
=jBk−∑i=1jAi+∑i=j+1NAi−(N−j)Bk
=(2j−N)Bk−∑i=1jAi+∑i=j+1NAi
と分解できます。
また,Bk≤A1 の場合は,∑i=1N∣Ai−Bk∣=∑i=1NAi−NBk であり,AN<Bk の場合は,∑i=1N∣Ai−Bk∣=NBk−∑i=1NAi となります。
jBk,(N−j)Bk は O(1) で求めることができ,∑i=1jAi,∑i=j+1NAi,∑i=1NAi は事前に O(N) で累積和を取っておけば O(1) で値を求めることができます。
A の要素と Bk の大小関係がどの場合に該当するのかは二分探索によって O(logN) で調べられるので,結局,答えに Bk が寄与する部分は O(logN) で値を求めることができます。
これを 1≤k≤M を満たすすべての k に対して求めた値の総和が答えになります。
計算量は O((N+M)logN) で,十分高速です。
なお,A, B のうち要素数が大きくない方をソートすることで,計算量は O((N+M)logmin(N,M)) になります。
実装例(C++)