Official

D - Long Waiting Editorial by sheyasutaka


実装方針

団体客 \(i-1\) が入店するまでを処理したものとし,その時刻を \(T_{i-1}\) とおきます.

団体客 \(i\) が先頭に来る時刻 \(A'_i\)\(\max(T_{i-1}, A_i)\) によって得られます.

この時点で,まだ退店していない客の人数合計が \(K\) 以下であれば,その時刻がそのまま団体客 \(i\) の入店時刻になります. そうでなければ,人数合計が \(K\) 以下になるまで,退店時刻が最も早い客を取り除くことを繰り返します.そして,\(A'_i\) と退店時刻との最大値が団体客 \(i\) の入店時刻とわかります.

退店時刻が最も早い客を取得するのは,優先度付きキューと呼ばれるデータ構造によって実現可能です.C++ などの主な言語においては標準で用意されているので,それを使用するのがよいでしょう.

現時点で退店していない客の人数合計は,客の入店ごとに人数合計を増やし,退店ごとに人数合計を減らすことで差分更新が可能です.

実装例 (C++)

#include <iostream>
using std::cin;
using std::cout;
#include <vector>
using std::vector;
using std::pair;
#include <queue>
using std::priority_queue;
using std::greater;
using std::max;

typedef long long int ll;
typedef pair<ll, ll> P;


ll n, k;
vector<ll> a, b, c;

void solve () {
	priority_queue<P, vector<P>, greater<P> > que;

	vector<ll> ans(n, -1);
	ll sum = 0;
	ll t = 0;
	for (ll i = 0; i < n; i++) {
		t = max(t, a[i]);
		while (sum + c[i] > k) {
			P q = que.top(); que.pop();
			t = max(t, q.first);
			sum -= q.second;
		}

		ans[i] = t;
		que.push({t + b[i], c[i]});
		sum += c[i];
	}

	for (ll i = 0; i < n; i++) {
		cout << ans[i] << "\n";
	}
}

int main (void) {
	cin >> n >> k;
	a.resize(n);
	b.resize(n);
	c.resize(n);
	for (ll i = 0; i < n; i++) {
		cin >> a[i] >> b[i] >> c[i];
	}

	solve();
	
	return 0;
}

posted:
last update: