「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 题解
> next 「ABC221E」LEQ 题解

> catalogue 「ABC221」题解

posted @ 2021-10-05 15:32  AlienCollapsar  阅读(275)  评论(0编辑  收藏  举报
// 生成目录索引列表 // ref: http://www.cnblogs.com/wangqiguo/p/4355032.html // modified by: zzq