公式

D - Online games 解説 by en_translator


Let \(X_1\) , \(X_2\) , \(\ldots\) , \(X_K\) be the sorted sequence of integer consisting of the days when some player started or retired from logging in; that is, that of \(X\) such that \(X=A_i\) or \(X=A_i+B_i\).
Then, for any \(Y\) satisfying \(X_i\leq Y \leq X_{i+1}-1\), the number of peopled who logged in on Day \(Y\) is constant. Also, for any \(Y\) such that \(Y<X_1\) or \(X_K\leq Y\), \(0\) people logged in, so we don’t have to consider these days. Therefore, the problem can be solved with a counter and an array that records the answer, with the counter and the array initialized to \(0\), updated for each \(i=1,2,\ldots,K-1\) with the following steps:

  • Increment the counter \(X_i\) by the number of people who started logging in on Day \(X_i\), and decrement by the number of people who retired from logging in.
  • Increase the number of days which \(C\) people logged in by \(X_{i+1}-X_i\), where \(C\) is the current value of the counter.

Since sorting \(\{ X_i\} \) costs \(O(N\log N)\) time, and the remaining operation can be done in an \(O(N)\) time, so the overall time complexity is \(O(N \log N)\). Therefore, the problem has been solved fast enough.

Sample code in C++:

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

#define N 200010
#define rep(i, n) for(int i = 0; i < n; ++i)

int main(void) {
	int n;
	int a, b;
	vector<pair<int, int> >x;
	int cnt;
	int ans[N];
	rep(i, N)ans[i] = 0;

	cin >> n;
	rep(i, n) {
		cin >> a >> b;
		x.push_back({ a,1 });
		x.push_back({ a + b,-1 });
	}

	sort(x.begin(), x.end());

	cnt = 0;
	rep(i, (x.size())-1) {
		cnt += x[i].second;
		ans[cnt] += ((x[i + 1].first) - (x[i].first));
	}

	rep(i, n - 1)cout << ans[i + 1] << " ";
	cout << ans[n] << endl;

	return 0;
}

投稿日時:
最終更新: