yamake's blog

主に競プロ、たまに自転車

Codeforces Round #610 A~Cまで

Codeforces Round #610のバチャをしました。

A, B1, B2の3完です。終了5分後にCが通りました......

 

 B問題は問題文が長くて読むのが大変でした。

 B2とCだけ解説してみます。

B2. K for the Price of One

問題概要

  • p円を持っている状態で一つあたりa[i]円の商品を何個か買いたい。
  • a[i]円の商品を買うときに、ちょうどk-1個のa[i]円より安い商品を無料で同時に受け取ることができる。
  • それぞれの商品は1度しか買えない。

最大で商品を何個買えるでしょう?

 

解説

値段を昇順にソートして、最初からx個を一つずつ、残ったものからk個セットで買えるだけ買っていくと答えが得られます。

 

反省

僕は残ったものからk個セットで買えるだけ買うところを、mod毎に累積和をとって二分探索したのですが、ここは二分探索をしなくても計算量は線形になります。

まあC++のupper_bound使った方が実装も軽いのでどちらでも良いのですが、計算量的に二分探索が必須だと思ったのはちょっと弱かったです。

B1も同じコードを投げるとACできます。

 

C. Petya and Exam

問題文が長くて読むのだけで結構時間がかかりました。

問題概要

  • T分間の試験を受ける。Petya君は任意のタイミングで試験を退出することができ、Petya君が退出するまでに解いた問題数を最大化したい。
  • それぞれの問題は簡単、難しいとわかれている。簡単な問題は一問あたりa分、難しい問題は一問あたりb分かかる。
  • それぞれの問題について時間関門t[i]が設定されている。Petya君が退出する時、その時刻より前に時間関門が設定されている問題は全て解かれている状態でなければならない。
  • Petya君は最大で何点獲得できるでしょうか。

 

解説

t[i]を昇順ソートして、t[i]-1の時刻と時刻Tだけ考えれば良いです。

 

それぞれの時刻で何問解けるかは

  • i-1番目以下の問題を全て解くのにかかる時間、
  • i番目以降に現れる簡単、難しい問題それぞれの数

をあらかじめ求めておくとO(1)で計算できます。

これによりO(N)で答えを求められます。