公式

B - 荷物の配送センター / Package Distribution Center 解説 by physics0523


この問題で要求されていることを整理します。

  • まず、配送センターは座標 \(S_i\) ( \(1 \le i \le M\) ) に存在する。
  • 全ての \(1 \le i \le N\) について、届け先が座標 \(D_i\) にある。この荷物については、 \(D_i\) に最も近い配送センターを見つけてそこから配送すればよい。

「最も近い配送センターを見つける」という点が難しそうです。どのようにすればよいでしょうか?

まず、データ構造を使って、以下の検索をします。

  • 座標が \(D_i\) 以上で最小の配送センターの座標 \(r\) を見つける
  • 座標が \(D_i\) 未満で最大の配送センターの座標 \(l\) を見つける

このとき、この \(2\) つのどちらかが最寄りの配送センターなので、この荷物については配送コストの最小値は \(\min(r-D_i,D_i-l)\) です。
上記のような検索は、ソート済みの配列から二分探索で行うこともできるほか、 C++ では set を用いると便利です。
実装の都合で、座標 \(\pm \infty\) (十分大きな値) に配送センターを置くと範囲外参照などを防止出来て楽になることがあります。

あとは、各荷物についての最小配送コストを足し合わせればよいです。

実装例 (C++):

#include<bits/stdc++.h>

using namespace std;
using ll=long long;

int main(){
  ll n,m;
  cin >> n >> m;
  vector<ll> d(n);
  for(auto &nx : d){cin >> nx;}
  set<ll> st;
  for(ll i=0;i<m;i++){
    ll s;
    cin >> s;
    st.insert(s);
  }
  st.insert(-1e18);
  st.insert(1e18);

  ll res=0;
  for(auto &nx : d){
    auto it=st.lower_bound(nx);
    ll add=(*it)-nx;
    it--;
    add=min(add,nx-(*it));
    res+=add;
  }
  cout << res << "\n";
  return 0;
}