首页 > 编程语言 >算法学习笔记(51)——区间问题

算法学习笔记(51)——区间问题

时间:2023-01-11 17:46:27浏览次数:62  
标签:10 le int 51 range 笔记 算法 端点 区间

区间问题

区间选点

题目链接:AcWing 905. 区间选点

题目描述

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

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

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

输入格式

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

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

输出格式

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

数据范围

\(1 \le N \le 10^5,\)

\(−10^9 \le a_i \le b_i \le 10^9\)

输入样例

3
-1 1
2 4
3 5

输出样例

2

算法思路

img

  1. 将每个区间按照右端点从小到大排序
  2. 从前往后依次枚举每一个区间
    • 如果当前区间已经包含点,则直接pass
    • 否则选择当前区间的右端点
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

int n;
struct Range
{
    int l, r;
    // 重载小于操作符,按照区间右端点排序
    bool operator< (const Range &w) const {
        return r < w.r;
    }
}range[N];

int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++ ) {
        int l, r;
        cin >> l >> r;
        range[i] = {l, r};
    }
    
    sort(range, range + n);
    
    int res = 0, ed = -2e9;
    for (int i = 0; i < n; i ++ )
        if (range[i].l > ed) {
            res ++;
            ed = range[i].r;
        }
     cout << res << endl;
     
     return 0;
}

最大不相交区间数量

题目链接:AcWing 908. 最大不相交区间数量

题目描述

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

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

输入格式

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

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

输出格式

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

数据范围

\(1 \le N \le 105,\)

\(−10^9 \le a_i \le b_i \le 10^9\)

输入样例

3
-1 1
2 4
3 5

输出样例

2

与上一题思路及代码完全相同。


区间分组

题目链接:AcWing 906. 区间分组

题目描述

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

输出最小组数。

输入格式

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

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

输出格式

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

数据范围

\(1 \le N \le 105,\)

\(−10^9 \le a_i \le b_i \le 10^9\)

输入样例

3
-1 1
2 4
3 5

输出样例

2

算法思路

  1. 将所有区间按左端点从小到大排序
  2. 从前往后处理每个区间
    • 判断能否将其放到某个现有的组中(判断当前区间的左端点是否小于某个现有的组的右端点)
      • 如果不存在这样的组,则开新组,然后再将其放进去
      • 如果存在这样的组,将其放进去,并更新当前组的Max_r

可以利用小根堆来动态维护最小的Max_r

#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

const int N = 100010;

int n;
struct Range
{
    int l, r;
    bool operator< (const Range &w) const {
        return l < w.l;
    }
}range[N];

int main()
{
    cin >> n;
    for (int i = 0 ; i < n; i ++ ) {
        int l, r;
        cin >> l >> r;
        range[i] = {l, r};
    }
    
    sort(range, range + n);
    
    priority_queue<int, vector<int>, greater<int>> heap;
    for (int i = 0; i < n; i ++ ) {
        auto r = range[i];
        if (heap.empty() || heap.top() >= r.l) heap.push(r.r);
        else {
            int t = heap.top();
            heap.pop();
            heap.push(r.r);
        }
    }
    
    cout << heap.size() << endl;
    
    return 0;
}

区间覆盖

题目链接:AcWing 907. 区间覆盖

题目描述

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

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

输入格式

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

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

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

输出格式

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

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

数据范围

\(1 \le N \le 10^5,\)

\(−10^9 \le a_i \le b_i \le 10^9,\)

\(−10^9 \le s \le t \le 10^9\)

输入样例

1 5
3
-1 3
2 4
3 5

输出样例

2

算法思路

img

  1. 将所有区间按照左端点从小到大排序
  2. 从前往后依次枚举每个区间,在所有能覆盖start的区间中,选择右端点最大的区间,然后将start更新成右端点的最大值
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

int n;
struct Range
{
    int l, r;
    bool operator< (const Range &w) const {
        return l < w.l;
    }
}range[N];

int main()
{
    int st, ed;
    cin >> st >> ed;
    cin >> n;
    for (int i = 0; i < n; i ++ ) {
        int l, r;
        cin >> l >> r;
        range[i] = {l, r};
    }
    
    sort(range, range + n);
    
    int res = 0;
    bool success = false;
    for (int i = 0; i < n; i ++ ) {
        int j = i, r = -2e9;
        while (j < n && range[j].l <= st) {
            r = max(r, range[j].r);
            j ++;
        }
        
        if (r < st) {
            res = -1;
            break;
        }
        
        res ++;
        if (r >= ed) {
            success = true;
            break;
        }
        
        st = r;
        i = j - 1;
    }
    
    if (!success) res = -1;
    cout << res << endl;
    
    return 0;
}

标签:10,le,int,51,range,笔记,算法,端点,区间
From: https://www.cnblogs.com/I-am-Sino/p/17044488.html

相关文章

  • Halcon学习笔记之支持向量机(二)
    在Halcon中模式匹配最成熟最常用的方式该署支持向量机了,在本例程中展示了使用支持向量机对卤素灯的质量检测方法。通过这个案例,相信大家可以对支持向量机的使用有一个更加......
  • 算法基础——排序
    本文仅供个人记录、分享快速排序快排是经典的排序算法之一,其平均的时间复杂度为O(nlogn)模板:785.快速排序-AcWing题库#include<iostream>usingnamespacestd;......
  • 电子设计教程51:16*16LED点阵屏驱动-74HC238译码器
      我尝试通过移位寄存器级联+三八译码器,实现用3跟控制线,驱动16*16LED点阵屏的效果。这是第三篇博客,讲述三八译码器的工作原理。  当驱动8×8LED点阵时,单片机至少需要发......
  • 力扣51. N 皇后(回溯法)
    按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互......
  • 基于python的小波阈值去噪算法
    小波图像去噪原理图像和噪声在经小波变换后具有不同的统计特性:图像本身的能量对应着幅值较大的小波系数,主要集中在低频(LL)部分;噪声能量则对应着幅值较小的小波系数,并分散在......
  • 极光笔记 | 如何为 iOS 16 创建一个实时活动
    01、iOS16中的LiveActivity(实时活动)是什么?​根据Apple官方描述,“实时活动是一项新功能,可帮助用户直接从锁定屏幕实时获知各种事情的进展,例如体育比赛、锻炼、拼车或......
  • Springcloud学习笔记54--postman传递date格式数据
    1.postman传递date格式数据通过定义PostMan全局变量传递postman.setGlobalVariable("inputtime",Date.parse(newDate("2021/12/16")));   ......
  • CVE-2020-2551
    前言2020年1月15日,Oracle发布了一系列的安全补丁,其中OracleWebLogicServer产品有高危漏洞,漏洞编号CVE-2020-2551,CVSS评分9.8分,漏洞利用难度低,可基于IIOP协议执行......
  • Java开发|移动开发|算法工程师……20-50K,欢迎投递
    FreemenAPP作为一款专注于程序员招聘求职的平台,主旨在于帮助更多的IT程序员技术能有一个更加便捷和轻松的求职环境,帮助更多IT程序员解决生活和工作之间的矛盾,增加程序员收......
  • RabbitMQ学习笔记05:Routing
    参考资料:RabbitMQtutorial-Routing—RabbitMQ  前言在之前的文章中我们构建了一个简单的日志系统,它可以广播消息到多个消费者中。在这篇文章中,我们打算实现仅订......