公式

B - パイプの接続 / Connecting Pipes 解説 by physics0523


パイプが \(1\) 本以上繋がった状態で有効長が \(l_i\) であるパイプを連結した際、全体の長さは \(l_i-K\) だけ伸びることに着目します。

基本的には、 \(l_i-K \ge 0\) であるパイプを全て繋げ、 \(l_i-K < 0\) であるパイプは繋がないことが最適です。
もし前者のようなパイプが繋がれず残っている場合は繋げて損しませんし、後者のパイプが繋がれている場合は除去することで長さが伸びます。

よって、達成可能なパイプの長さの最大長は基本的に \(K + \sum \max(l_i-K,0)\) です。
ただし、これには例外があります。
全てのパイプの有効長が \(K\) 未満である場合、先ほどの式を計算した結果は \(K\) となりますが、実際は最も有効長が長いパイプを単独で使うのが最善なので、そのようなケースを場合分けします。

この解法の時間計算量は \(O(N)\) です。

実装例 (C++):

#include<bits/stdc++.h>

using namespace std;
using ll=long long;

int main(){
  ll N,D,K,C;
  cin >> N >> D >> K >> C;
  ll one=-8e18,con=K;
  vector<ll> l;
  for(ll i=0;i<N;i++){
    ll A,B;
    cin >> A >> B;
    if(B){A=max(0ll,A-C);}
    one=max(one,A);
    con+=max(0ll,A-K);
  }
  if(one<K){con=-8e18;}
  ll best=max(one,con);
  if(best>=D){cout << best << "\n";}
  else{cout << "-1\n";}
  return 0;
}