第7回日本情報オリンピック 本選 C-ダーツ(精選23)
問題
https://www.ioi-jp.org/joi/2007/2008-ho-prob_and_sol/2008-ho.pdf#page=6
ダーツを4本まで投げ上限Mを超えない得点の最大値を求めます。
得点はP[N]でN<=1000です。
考察
普通にループを回すのでは1000^4=1兆になりとても間に合いません。
二分探索のパワーを十分に使うため2本づつ投げることにすると間に合います。
投げない場合を考えて得点の配列に0を加えます。
upper_boundで出力したitr(Mを超える最初の要素のitr)の1つ前の要素(*(itr-1))の最大値を出力します。
ACしたコード
#include <bits/stdc++.h> using namespace std; int main(){ int N,M; cin>>N>>M; vector<int>P(N+1); vector<int>Q((N+1)*(N+1)); for(int i=1;i<=N;i++){ cin>>P[i]; } P[0]=0; int ans=0; for(int i=0;i<=N;i++){ for(int j=0;j<=N;j++){ Q[i*(N+1)+j]=P[i]+P[j]; } } sort(Q.begin(),Q.end()); for(int i=0;i<(N+1)*(N+1);i++){ if(Q[i]>M) break; auto itr=upper_bound(Q.begin(),Q.end(),M-Q[i]); ans=max(ans,Q[i]+*(itr-1)); } cout<<ans<<endl; }