「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;
}