AtCoder ABC 172 反省
結果
A, B, D 問題は AC した。C 問題は解けず。E, F 問題は見たけど解けそうにないと思ってすぐにあきらめた(前回よりほんの少し成長?)。
C 問題復習
問題概要
A, B 2つの机の上にそれぞれ 冊の本が乗っている。それぞれの本は読むのに 分かかる。
- 本が乗っている机を選び、一番上の本を読む。読み終わった本を机から取り除く。
という行為を繰り返すとき、 分以内に読める本の最大の冊数を求めよ。
解き方
「しゃくとり法」というやつを使うらしい。しゃくとり法一般について詳しいことはわからないが、この問題の場合に限ってしゃくとり法による解法をまとめてみようと思う。
この問題は机 A から本を 冊、机 B から本を 冊読むとして、所要時間が 分を超えない範囲で の最大値を求める問題ということができる。机 A から本を 冊 読むのにかかる時間 は
しゃくとり法は について を ~ まで昇順で全探索し、 についてはそれぞれの に関して を から降順に探索することで をどんどん更新していく。 は 以下なので、となった場合はその時点で探索を打ち切ることができる。また、それぞれの とペアを組む は に関して単調減少なので、例えば とペアを組む の値が であったなら、 に対しては から探索を始めればよい。
しゃくとり法の計算量等について詳しいことはこれから調べようと思う。
ACしたコード
#include<bits/stdc++.h> using namespace std; int main(){ int64_t n,m; int64_t k; cin >>n>>m>>k; vector<int64_t>a(n); vector<int64_t>b(m); vector<int64_t>as(n+1,0); vector<int64_t>bs(m+1,0); for(int64_t i=0;i<n;i++){ cin>>a.at(i); as.at(i+1)=as.at(i)+a.at(i); } for(int64_t i=0;i<m;i++){ cin>>b.at(i); bs.at(i+1)=bs.at(i)+b.at(i); } int64_t tmp=m; int64_t ans=0; for(int64_t i=0;i<n+1;i++){ if(as.at(i)>k)break; for(int64_t j=tmp;j>=0;j--){ if(as.at(i)+bs.at(j)<=k){ ans=max(ans,i+j); tmp=j; break; } } } cout <<ans<<endl; }
雑記
最近プログラミングに関しては Progate の HTML & CSS の講座に時間を割いていて競プロの練習ができていない。その割に今回のコンテストでは良い結果が出てしまったので慢心しないようにしたい。