题目
题意翻译
题目大意:
给你n个区间,求被这些区间覆盖层数为k(k<=n)k(k<=n)的点的个数
输入格式:
第一行一个整数,nn,n<=2*10^5n<=2∗10
5
以下nn行,每行有两个整数,即这个区间的左右端点l,r(0<=l<=r<=10^{18})l,r(0<=l<=r<=10
18
)
输出格式:
nn个整数,即每个被覆盖层数对应的点的个数
感谢@守望 提供翻译
题目描述
You are given n n segments on a coordinate line; each endpoint of every segment has integer coordinates. Some segments can degenerate to points. Segments can intersect with each other, be nested in each other or even coincide.
Your task is the following: for every k \in [1…n] k∈[1…n] , calculate the number of points with integer coordinates such that the number of segments that cover these points equals k k . A segment with endpoints l_i l
i
and r_i r
i
covers point x x if and only if l_i \le x \le r_i l
i
≤x≤r
i
.
输入输出格式
输入格式:
The first line of the input contains one integer n n ( 1 \le n \le 2 \cdot 10^5 1≤n≤2⋅10
5
) — the number of segments.
The next n n lines contain segments. The i i -th line contains a pair of integers l_i, r_i l
i
,r
i
( 0 \le l_i \le r_i \le 10^{18} 0≤l
i
≤r
i
≤10
18
) — the endpoints of the i i -th segment.
输出格式:
Print n n space separated integers cnt_1, cnt_2, \dots, cnt_n cnt
1
,cnt
2
,…,cnt
n
, where cnt_i cnt
i
is equal to the number of points such that the number of segments that cover these points equals to i i .
输入输出样例
输入样例#1: 复制
3
0 3
1 3
3 8
输出样例#1: 复制
6 2 1
输入样例#2: 复制
3
1 3
2 4
5 7
输出样例#2: 复制
5 2 0
说明
The picture describing the first example:
Points with coordinates [0, 4, 5, 6, 7, 8] [0,4,5,6,7,8] are covered by one segment, points [1, 2] [1,2] are covered by two segments and point [3] [3] is covered by three segments.
The picture describing the second example:
Points [1, 4, 5, 6, 7] [1,4,5,6,7] are covered by one segment, points [2, 3] [2,3] are covered by two segments and there are no points covered by three segments.
思路
我在做这道题时,乍一看,诶,这不是一个前缀和扫一遍吗?于是我就非常愉快的打了一遍。。。然后就 GG 了。
RE 完之后,我再去看了一遍数据范围 – WOC,为什么 l,r 是 1e18?好吧,那这道题还没有想象中的那么水。。。
不过很快大家就能注意到:n 只有 20 万。这说明了什么呢?说明前缀和改变的节点最多只有 40 万个。那么我们把这些节点存起来再一排序,然后扫一遍不就得了?
那么我们就用一个 now 记录当前段被覆盖了几次,然后枚举排序后前缀和改变的节点,把每次改变之前的一段中的节点数加入覆盖数为 now 的答案,最后修改 now 的值即可。还要注意一点:每一个线段的左端点和右端点的节点类型是不一样的,遇到左端点要 now++,右端点则要 now–。
下面附上代码吧:
代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int n;long long ans[200005];
struct nod{
long long p;int k;
};
bool cmp(nod i,nod j){return i.p==j.p?i.k<j.k:i.p<j.p;}
vector<nod> q;
int main()
{
long long l,r;
cin>>n;
for(int i=1;i<=n;i++)
cin>>l>>r,q.push_back((nod){l,1}),q.push_back((nod){r+1,-1});
sort(q.begin(),q.end(),cmp);
long long last=0,now=0;
for(int i=0;i<q.size();i++)
{
long long nex=q[i].p;
ans[now]+=q[i].p-last,now+=q[i].k,last=nex;
}
for(int i=1;i<=n;i++)
cout<<ans[i]<<" ";
}