1. 程式人生 > 其它 >「ABC221D」Online games 題解

「ABC221D」Online games 題解

D - Online games

Time Limit: \(2\; sec\) / Memory Limit: \(1024\; MB\)

Score : \(400\; points\)

Problem Statement|題目描述

  • There is an online game with \(N\) registered players.

  • 有一個已經註冊了 \(N\) 名玩家的線上遊戲。

  • Today, which is the \(10^{100}\) -th day since its launch, the developer Takahashi examined the users' login history. It turned out that the \(i\)

    -th player logged in for \(B_i\) consecutive days from Day \(A_i\) , where Day \(1\) is the launch day, and did not log in for the other days. In other words, the \(i\)-th player logged in on Day \(A_i\) , \(A_{i+1}\) , \(…\) , \(A_i+B_i-1\) , and only on those days.

  • 今天,也就是它釋出的第 \(10^{100}\) 天,開發者 Takahashi 檢查了使用者的登入歷史。事實證明,第 \(i\)

    個玩家從 \(A_i\)
    開始連續登入 \(B_i\) 天,其中第 \(1\) 天是釋出日。換句話說,第 \(i\) 個玩家只在 \(A_i\)\(A_{i+1}\)\(…\)\(A_i+B_i-1\)天登入。

  • For each integer \(k\) such that \(1\leq k\leq N\), find the number of days on which exactly \(k\) players logged in.

  • 對於每個整數 \(k\) ,使 \(1\leq k\leq N\), 查詢 \(k\) 個玩家登入的天數。

Constraints|資料範圍

  • \(1\leq N\leq 2\times 10^5\)

  • \(1\leq A_i\leq 10^9\)

  • \(1\leq B_i\leq 10^9\)

  • All values in input are integers.

  • \(1\leq N\leq 2\times 10^5\)

  • \(1\leq A_i\leq 10^9\)

  • \(1\leq B_i\leq 10^9\)

  • 輸入中的所有值都是整數。

Input|輸入

Input is given from Standard Input in the following format:

\(N\)
\(A_1\ B_1\)
\(A_2\ B_2\)
\(:\)
\(A_N\ B_N\)

  • 輸入為以下格式的標準輸入(中間有空格):

\(N\)
\(A_1\ B_1\)
\(A_2\ B_2\)
\(:\)
\(A_N\ B_N\)

Output|輸出

  • Print \(N\) integers with spaces in between, as follows:

\(D_1\ D_2\ …\ D_N\)

  • 輸出 \(N\) 個整數,中間有空格,如下所示​

\(D_1\ D_2\ …\ D_N\)

  • Here, \(D_i\) denotes the number of days on which exactly \(k\) players logged in.

  • 在這裡,\(D_i\) 表示有 \(k\) 個玩家登入的天數。

Sample Input 1 |樣例輸入 1

3
1 2
2 3
3 1

Sample Output 1 |樣例輸出 1

2 2 0

  • The first player logged in on Day \(1, 2\), the second player logged in on Day \(2, 3, 4\), and the third player logged in on Day \(3\) only.

  • 第一名玩家在第 \(1,2\) 天登入,第二名玩家在第 \(2,3,4\) 天登入,第三名玩家僅在第 \(3\) 天登入

  • Thus, we can see that Day \(1, 4\) had \(1\) player logged in, Day \(2, 3\) had \(2\) players logged in, and the other days had no players logged in.

  • 因此,我們可以看到第 \(1\) 天、第 \(4\) 天有 \(1\) 名玩家登入,第 \(2\) 天、第 \(3\) 天有 \(2\) 名玩家登入,其他幾天沒有玩家登入。

  • The answer is: there were \(2\) days with exactly \(1\) player logged in, \(2\) days with exactly \(2\) players logged in, and \(0\) days with exactly \(3\) players logged in.

  • 答案是:有 \(2\) 天只有 \(1\) 名玩家登入,有 \(2\) 天只有 \(2\) 名玩家登入,有 \(0\) 天只有 \(3\) 名玩家登入。

Sample Input 2 |樣例輸入 2

2
1000000000 1000000000
1000000000 1000000000

Sample Output 2 |樣例輸出 2

0 1000000000

  • There may be two or more players who logged in during the same period.

  • 可能有兩個或更多玩家在同一時間登入。


分析

斟酌再三,我使用了差分

由於資料比較大,所以需要離散化操作。
離散化常態:\(STL+\)結構體

對於結構體陣列,我一開始開了一個 \(d[200010]\) ,但還是不夠給掛了,一怒之下,我把結構體寫在了 \(vector\) 裡面

struct daily{
	int num;
	int x;
};
vector<daily>d; 
map<ll,int>p;
scanf("%d",&n);
for(int i=1;i<=n;i++){
	ll a,b;
	scanf("%lld%lld",&a,&b);
	if(p[a])d[p[a]].x++;
	else d.push_back((daily){a,1}),p[a]=d.size()-1;
	if(p[a+b])d[p[a+b]].x--;
	else d.push_back((daily){a+b,-1}),p[a+b]=d.size()-1;
}

使用 \(map\) 陣列 \(p\) 來指示 \(p_k\)\(d\) 中的位置。
\(d_{k'}\) 中,\(num\) 表示離散化前 \(k'\) 真實的大小 \(k\)\(x\) 表示差分的值。

bool cmp(daily fir,daily sec){
	return fir.num<sec.num;
}
sort(d.begin(),d.end(),cmp);

\(num_k\) 的真實值 \(k'\) 排序。(也就是按日期排序)

ll sum=0;
for(int i=0;i<d.size();i++){
	a[sum]+=(d[i].num-d[i-1].num);
	sum+=d[i].x;
}

統計每次變化後,登入的人數 \(sum\) ,將其登入的天數存進答案 \(a_{sum}\) 中。

AC程式碼

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=200010;
int n;
struct daily{
	int num;
	int x;
};
vector<daily>d; 
map<ll,int>p;
ll a[maxn];
bool cmp(daily fir,daily sec){
	return fir.num<sec.num;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		ll a,b;
		scanf("%lld%lld",&a,&b);
		if(p[a])d[p[a]].x++;
		else d.push_back((daily){a,1}),p[a]=d.size()-1;
		if(p[a+b])d[p[a+b]].x--;
		else d.push_back((daily){a+b,-1}),p[a+b]=d.size()-1;
	}
	sort(d.begin(),d.end(),cmp);
	ll sum=0;
	for(int i=0;i<d.size();i++){
		a[sum]+=(d[i].num-d[i-1].num);
		sum+=d[i].x;
	}
	for(int i=1;i<=n;i++){
		printf("%lld ",a[i]);
	}
	return 0;
} 

$$-----CONTINUE------$$

< last 「ABC221C」Select Mul 題解