【CF1000C】 Covered Points Count

题目

题意翻译
题目大意:

给你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]<<" ";
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值