区间覆盖(重叠)问题

区间覆盖总点数(区间合并)

P2082 区间覆盖(加强版)

题目描述

已知有\(N\)个区间,每个区间的范围是\([si,ti]\),请求出区间覆盖后的总长。

输入格式

N s1 t1 s2 t2 …… sn tn

输出格式

共一行,一个正整数,为覆盖后的区间总长。

输入

3
1 100000
200001 1000000
100000000 100000001

输出

900002

说明/提示

【数据范围】

对于\(40\%\)的数据 \(N≤1000,0<Si<Ti≤10000\)

对于\(100\%\)的数据 \(N≤10^5,0<Si<Ti≤10^{17}\),且为整数

  • 时间复杂度:\((nlogn)\)

代码

//区间覆盖,求区间的覆盖点数
#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
using LL=long long;
pair<LL,LL> a[100005];
int n;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%lld%lld",&a[i].fi,&a[i].se);
    sort(a+1,a+1+n);
    LL res=0,s=a[1].fi,e=a[1].se;
    for(int i=2;i<=n;i++)
        if(a[i].fi<=e)e=max(e,a[i].se);
        else
        {
            res+=e-s+1;
            s=a[i].fi,e=a[i].se;
        }
    res+=e-s+1;
    printf("%lld",res);
    return 0;
}

最少覆盖区间区间数

907. 区间覆盖

给定 \(N\) 个闭区间 \([a_i,b_i]\) 以及一个线段区间 \([s,t]\),请你选择尽量少的区间,将指定线段区间完全覆盖。

输出最少区间数,如果无法完全覆盖则输出 \(−1\)

输入格式

第一行包含两个整数 \(s\)\(t\),表示给定线段区间的两个端点。

第二行包含整数 \(N\),表示给定区间数。

接下来 \(N\) 行,每行包含两个整数 \(a_i,b_i\),表示一个区间的两个端点。

输出格式

输出一个整数,表示所需最少区间数。

如果无解,则输出 \(−1\)

数据范围

\(1≤N≤10^5\),
\(−10^9≤a_i≤b_i≤10^9\),
\(−10^9≤s≤t≤10^9\)

输入样例:

1 5
3
-1 3
2 4
3 5

输出样例:

2
  • 时间复杂度:\(O(nlogn)\)

代码

//区间覆盖,求最少覆盖区间数
#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
int n,s,t;
pair<int,int> a[100005];
int main()
{
    scanf("%d%d%d",&s,&t,&n);
    for(int i=1;i<=n;i++)scanf("%d%d",&a[i].fi,&a[i].se);
    sort(a+1,a+1+n);
    int res=0,r=-2e9;
    for(int i=1;i<=n;i++)
    {
        int j=i;
        r=-2e9;
        while(j<=n&&a[j].fi<=s)
        {
            r=max(r,a[j].se);
            j++;
        }
        res++;
        if(r<s||r>=t)break;
        s=r;
        i=j-1;
    }
    printf("%d",r>=t?res:-1);
    return 0;
}

覆盖区间的最少点数(不重叠的区间数)

905. 区间选点

给定 \(N\) 个闭区间 \([a_i,b_i]\),请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。

输出选择的点的最小数量。

位于区间端点上的点也算作区间内。

输入格式

第一行包含整数 \(N\),表示区间数。

接下来 \(N\) 行,每行包含两个整数 \(a_i,b_i\),表示一个区间的两个端点。

输出格式

输出一个整数,表示所需的点的最小数量。

数据范围

\(1≤N≤10^5\),
\(−10^9≤a_i≤b_i≤10^9\)

输入样例:

3
-1 1
2 4
3 5

输出样例:

2

908. 最大不相交区间数量

给定 \(N\) 个闭区间 \([a_i,b_i]\),请你在数轴上选择若干区间,使得选中的区间之间互不相交(包括端点)。

输出可选取区间的最大数量。

输入格式

第一行包含整数 \(N\),表示区间数。

接下来 \(N\) 行,每行包含两个整数 \(a_i,b_i\),表示一个区间的两个端点。

输出格式

输出一个整数,表示可选取区间的最大数量。

数据范围

\(1≤N≤10^5\),
\(−10^9≤a_i≤b_i≤10^9\)

输入样例:

3
-1 1
2 4
3 5

输出样例:

2
  • 时间复杂度:\(O(nlogn)\)

代码

//区间不覆盖,覆盖所有区间的最少点数
#include<bits/stdc++.h>
using namespace std;
int n;
struct Range
{
    int l,r;
    bool operator<(const Range &o)
    {
        return r<o.r;
    }
}a[100005];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d%d",&a[i].l,&a[i].r);
    sort(a+1,a+1+n);
    int res=0,t=-2e9;
    for(int i=1;i<=n;i++)
        if(a[i].l>t)
        {
            res++;
            t=a[i].r;
        }
    printf("%d",res);
    return 0;
}

最少内部不相交区间组数

906. 区间分组

给定 \(N\) 个闭区间 \([a_i,b_i]\),请你将这些区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。

输出最小组数。

输入格式

第一行包含整数 \(N\),表示区间数。

接下来 \(N\) 行,每行包含两个整数 \(a_i,b_i\),表示一个区间的两个端点。

输出格式

输出一个整数,表示最小组数。

数据范围

\(1≤N≤10^5\),
\(−10^9≤a_i≤b_i≤10^9\)

输入样例:

3
-1 1
2 4
3 5

输出样例:

2
  • 时间复杂度:\(O(nlogn)\)

代码

//区间分组,组内区间互不相交的最少组数
#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
int n;
pair<int,int> a[100005];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d%d",&a[i].fi,&a[i].se);
    sort(a+1,a+1+n);
    priority_queue<int,vector<int>,greater<int> > q;
    for(int i=1;i<=n;i++)
    {
        auto t=a[i];
        if(q.empty()||q.top()>=t.fi)q.push(t.se);
        else
        {
            q.pop();
            q.push(t.se);
        }
    }
    printf("%d",q.size());
    return 0;
}

最多重叠区间数

#34. 「LYOI2016 Summer」Doges

题目描述

在一个遥远的地方,住着 \(n\) 只 Doge,它们分别被编号为 \(1\)\(n\) 之间的正整数。

有一天,一个叫 Jrisme 的人来到这里,进行了一些「虐狗」行为。具体的,Jrisme 每次会虐编号连续的一些 Doge。现给出每次虐狗的区间,求最幸运(被虐次数最多)Doge 被虐了多少次。

输入格式

第一行两个正整数 \(n\)\(m\),分别表示 Doge 的数量和 Jrisme 的虐狗次数。

从第二行开始,之后的 \(m\) 行,第 \(i\) 行为两个正整数 \(l_i\)\(r_i\),表示 Jrisme 虐了编号在区间 \([l_i,r_i]\) 内的 Doge。

输出格式

一行一个整数,最幸运的 Doge 的被虐次数。

输入样例

10 3
1 4
4 7
4 9

输出样例

3

数据范围与提示

对于 \(30\%\) 的数据,\(n,m\leq 1000\)
对于另外 \(20\%\) 的数据,\(n\leq 10^6\)
对于另外 \(20\%\) 的数据,\(n\leq 5\times 10^5\)
对于另外 \(20\%\) 的数据,\(m\leq 5000\)
对于 \(100\%\) 的数据,\(1\leq n\leq 10^9\)\(1\leq m\leq 200000\)\(1\leq l_i \leq r_i \leq n\)

  • 时间复杂度:\(O(nlogn)\)

代码

//区间重叠,最多重叠区间数
#include<bits/stdc++.h>
using namespace std;
int n,m;
struct Range
{
    int x,flag;
    bool operator<(const Range &o)
    {
        if(x!=o.x)return x<o.x;
        return o.flag<flag;
    }
}a[400005];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&a[i].x,&a[i+m].x);
        a[i].flag=1,a[i+m].flag=-1;
    }
    sort(a+1,a+1+2*m);
    int res=0,t=0;
    for(int i=1;i<=2*m;i++)
        t+=a[i].flag,res=max(res,t);
    printf("%d",res);
    return 0;
}
posted @ 2021-11-06 09:35  zyy2001  阅读(654)  评论(0编辑  收藏  举报