ログインしてください。
公式
E - 図書館の蔵書点検 / Library Inventory Check 解説
by
E - 図書館の蔵書点検 / Library Inventory Check 解説
by
physics0523
この問題は、イベントソートと segment tree を用いることで解くことができます。
まず、「修理の完了」と「貸し出し計画」を統一的に「イベント」として扱い、時系列順に並べます。但し、同じ日に来る修理の完了と貸し出し計画は、修理の完了が先になるように並べておきます。
次に、全てのイベントについて以下を繰り返します。
- 区間和を求める segment tree を用意する。これを \(seg\) と呼ぶ。
- 「修理の完了」が来た場合、 \(seg\) に修理が完了した本の情報を追加する。
- 「貸し出し計画」が来た場合、現時点での \(seg\) がその時点で修理が完了している本の情報を反映している。よって、この時点での \(seg\) の区間和を適切に調べることで答えが分かる。
時間計算量は \(O((N+Q) \log (N+Q))\) です。
実装例 (C++):
#include<bits/stdc++.h>
#include<atcoder/segtree>
using namespace std;
using namespace atcoder;
using ll=long long;
ll op(ll a,ll b){return (a+b);}
ll e(){return 0;}
typedef struct{
ll day;
ll type;
ll x;
ll y;
}query;
bool comp(const query &l,const query &r){
if(l.day==r.day){
return (l.type<r.type);
}
return (l.day<r.day);
}
int main(){
ll N,Q;
cin >> N >> Q;
vector<query> vq;
for(ll i=0;i<N;i++){
ll A,D,V;
cin >> A >> D >> V;
vq.push_back({D,-1,i,A*V});
}
for(ll i=0;i<Q;i++){
ll L,R,T;
cin >> L >> R >> T;
vq.push_back({T,i,L-1,R});
}
sort(vq.begin(),vq.end(),comp);
segtree<ll,op,e> seg(N);
vector<ll> res(Q);
for(auto &nx : vq){
if(nx.type==-1){
seg.set(nx.x,nx.y);
}
else{
res[nx.type]=seg.prod(nx.x,nx.y);
}
}
for(auto &nx : res){
cout << nx << "\n";
}
return 0;
}
投稿日時:
最終更新:
