51nod3110 小明爱区间

2021/10/9 23:38:51

本文主要是介绍51nod3110 小明爱区间,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

3110 小明爱区间

小明最近非常喜欢区间,于是他想出来这样一个问题:
给定平行于x轴的 n 条线段。每个线段的左右端点坐标都是整数。有些线段可以退化成点。线段之间可以相互交叉,嵌套,甚至重合。

这样所有 x 轴上的整数点最少被 0 条线段覆盖,最多同时被 n 条线段覆盖。

你的任务是:求出 x 轴上,分别被 k 条线段覆盖的,坐标为整数的点的数量。(1\leq k\leq n)。

注意:被线段的左右端点覆盖也算是覆盖。

输出共 n 个数,第 1 个数表示被 1 条线段覆盖的整点数量,第 2 个数表示被2线段覆盖的整点数量......

输入

输入的第一行包含一个整数n(1≤n≤2*10^5)—线段的数量。
接下来的n行。
第i行包含一对整数li,ri(0≤li≤ri≤10^18),表示第i段的端点。

输出

输出包括一行n个数字,第i个数字表示被i条线段覆盖的点的数目。

数据范围

对于10%的数据,1<= n <= 8
对于50%的数据,1 <= n<= 1024
对于100%的数据,1 <= n <= 200000
0≤li≤ri≤10^18。

输入样例

3
0 3
1 3
3 8

输出样例

6 2 1

样例解释

解析:

我们知道,每一个区间的贡献是1,那么我便可以在区间的左端点加1,右端点减1,这样可以累加过去,便可以实现这个区间的每一个数字加1,对每一个区间都这样操作,我们不用遍历每一个数字,对区间的端点从小到大排序,对于排序后的端点,我们可以O(1)计算出这个区间的有多少个数字有着相同的贡献,贡献的数值直接累加端点值即可,具体看代码,时间复杂度O(nlogn)。

放代码:

#include <bits/stdc++.h>
#define N 200010
#define ll long long
using namespace std;
int n,ans[N];
struct node
{
    ll pos;
    int id;//id==0?l:r
    bool operator < (const node &t)
    {
        return pos<t.pos;
    }
}p[N<<1];
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>p[i*2-1].pos>>p[i*2].pos;
        p[i*2].pos++,p[i*2].id=1;
    }
    sort(p+1,p+1+2*n);
    p[0]=p[1];
    for(int i=1,cnt=0;i<=2*n;i++)
    {
        ans[cnt]+=p[i].pos-p[i-1].pos;
        if(!p[i].id)cnt++;
        else cnt--;
    }
    for(int i=1;i<=n;i++)cout<<ans[i]<<" \n"[i==n];
    return 0;
}



这篇关于51nod3110 小明爱区间的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程