「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\)
-
今天,也就是它釋出的第 \(10^{100}\) 天,開發者 Takahashi 檢查了使用者的登入歷史。事實證明,第 \(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;
}