[JOI精進録] 難易度6「Relay」(JOIG2021/2022 春合宿A)

問題リンク

atcoder.jp

問題概要

N人の人i (1 \le i \le N)がいて、それぞれにA_iB_iが定められている。
この中から3人i,j,k (1 \le i,j,k \le N)を選び、A_i + A_k + A_j + max(B_i,B_k) + max(B_k,B_j)を最小化してください。

解説

AC解法 (100/100点)

1 \le j <  k <  i \le Nとして選ぶことで2つのBの最大値の和を最小化することができます。今後はこの制約で選ぶことを考えます。
kを全探索します。
jA_jが最小になるjiA_i+B_iが最小になるiを選ぶのが最適です。
これは累積minを使って前計算O(N)、クエリO(1)で求められ、全探索にO(N)かかるので全体O(N)でこの問題を解くことができました。

ACコード

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

int main(){
  int n,r(numeric_limits<int>::max()); cin >> n;
  vector<pair<int,int>> A(n); for (auto& [b,a]:A) cin >> a >> b;
  sort(A.begin(),A.end());
  vector<int> acc(n+1,r); for (int i(n-1);i > -1;--i) acc[i]=min(acc[i+1],A[i].first+A[i].second); int mn(A[0].second);
  for (int i(1);i < n-1;++i){
    r=min(r,A[i].first+A[i].second+mn+acc[i+1]);
    mn=min(mn,A[i].second);
  }
  cout << r << endl;
}

提出結果

atcoder.jp