実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: 602
問題概要
台のソリがあり、ソリ
を引くために必要なトナカイは
匹である。また、各トナカイが引けるソリは高々1台である。以下の形式のクエリが
個与えられるので、順に処理せよ。
- クエリ :
- 整数
が与えられるので、
匹のトナカイが最大何台のソリを引けるか求めよ。
- 整数
制約
- 入力はすべて整数。
考察
を昇順ソートしたとき、各クエリで求めたいのは
を満たす最大の
である。
この を愚直に求めようとすると
を
から順に足していくことになるが、制約の大きさから、各クエリに対して行っていくと実行時間制限に間に合わない。
そこで、毎回 を最初から足していくのではなくて、事前に
という配列を用意しておき、各クエリではこの (単調増加な) 配列に対して二分探索を行うことで、対数時間でクエリを処理することが可能になる。
配列 は累積和というテクニックで、今回のような「数列上のある範囲の総和を高速で求めたい」ときに有効な手段である。
なお、 であるから、二分探索で得られたインデックスから
引く必要があることに注意しよう。
コード
#include <bits/stdc++.h> using namespace std; #define all(x) (x).begin(), (x).end() #define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++) // ======================================== // int main() { int N, Q; cin >> N >> Q; vector<ll> R(N); rep(i, 0, N) cin >> R[i]; sort(all(R)); vector<ll> ps(N + 1, 0); rep(i, 0, N) ps[i + 1] = ps[i] + R[i]; while (Q--) { ll X; cin >> X; cout << upper_bound(all(ps), X) - ps.begin() - 1 << endl; } }
実装時間: 35分