実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: 408
問題概要
数直線上に 個の村がある。
番目の村は座標
にあって、人口は
人である。次の形式で与えられる
個のクエリに答えよ。
- クエリ : 整数
が与えられるので、座標
以上
以下の村の人口の総和を求めよ。
制約
- 入力は全て整数。
考察
クエリでは、配列のある区間における総和を聞かれているので、累積和を用いれば効率よく求められそう。
そこで、座標 以下で最も座標が大きい村のそれぞれのインデックス
を求めたい。幸いなことに本問では
が昇順ソートされた状態で与えられるので、この配列に対して二分探索をしてやることで対数時間で処理できる。
二分探索で求めたインデックスは累積和の計算時に開区間として使うので、
の方は
upper_bound
を用いることで、インデックスに をしないで済む。
以上で、計算量 のアルゴリズムでこの問題を解くことができる。
コード
#include <bits/stdc++.h>usingnamespacestd; using ll = longlong; #define all(x) (x).begin(), (x).end()#define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++)// ======================================== //intmain() { int N; cin>> N; vector<int> X(N); rep(i, 0, N) cin>> X[i]; vector<ll> P(N); rep(i, 0, N) cin>> P[i]; int Q; cin>> Q; vector<ll> ps(N + 1, 0); rep(i, 0, N) ps[i + 1] = ps[i] + P[i]; while (Q--) { int L, R; cin>> L >> R; int idx_L = lower_bound(all(X), L) - X.begin(); int idx_R = upper_bound(all(X), R) - X.begin(); cout<< ps[idx_R] - ps[idx_L] << endl; } }
実装時間: 25分
累積和と二分探索を組み合わせて解く良問。