Official

C - 山の見える展望台 / Observatory with a Mountain View Editorial by kyopro_friends Editorial for printing


この問題は累積和を用いて解くことができます。

山の番号は問題に影響しないため、標高の降順にソートしてよいです。
その後、美しさの累積和を求めておきます。

このとき、各調査において求めるものは、「先頭からいくつかの山の美しさの和」であるため、標高の配列を二分探索し何番目の山までが標高 \(L_j\) 以上であるかを求め、美しさの累積和の配列を参照することで求めることができます。

よって全体で \(O((N+Q)\log N)\) でこの問題を解くことができます。

以下の実装例では、山を標高の昇順にソートし、「標高が低い山の美しさを全体から引く」として答えを求めています。

実装例 (C++)

#include<bits/stdc++.h>
using namespace std;

int main(){
  int n, q;
  cin >> n >> q;
  vector<pair<int,int>>yp(n);
  for(int i=0; i<n; i++) cin >> yp[i].first >> yp[i].second;
  sort(yp.begin(),yp.end());

  // 累積和
  vector<long long>s({0});
  for(int i=0; i<n; i++){
    s.push_back(s.back() + yp[i].second);
  }

  for(int k=0; k<q; k++){
    int l;
    cin >> l;
    int i = lower_bound(yp.begin(), yp.end(), make_pair(l, 0)) - yp.begin();
    cout << s.back() - s[i] << endl;
  }
}

実装例 (Python)

import bisect
N, Q = map(int, input().split())
YP = []
for _ in range(N):
  Y, P = map(int,input().split())
  YP.append((Y, P))
YP.sort()

# 累積和
S=[0]
for _, p in YP:
  S.append(S[-1]+p)

for _ in range(Q):
  L = int(input())
  i = bisect.bisect_left(YP, (L, 0))
  print(S[-1] - S[i])

posted:
last update: