贪心:区间问题

news/2025/2/15 20:28:45/

目录

  • 前言
  • 区间选点
    • Code
  • 最大不相交区间数量
    • Code
  • 区间分组
    • Code
  • 区间覆盖
    • Code


前言

贪心真是玄学,规律全靠猜,证实靠样例!


区间选点

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

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

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

输入格式
第一行包含整数 NNN,表示区间数。

接下来 NNN 行,每行包含两个整数 ai,bia_i,b_iai,bi,表示一个区间的两个端点。

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

数据范围
1≤N≤105,1≤N≤10^5,1N105,
−109≤ai≤bi≤109−10^9≤a_i≤b_i≤10^9109aibi109

输入样例:

3
-1 1
2 4
3 5

输出样例:

2

思路:对于所有区间按照右端点进行一遍sort,然后从第一个区间开始,选择右端点作为那个要包含的其中一个点choice因为这个choice很有希望能处在往后面几个区间的范围里,这样就减少了要选择点的次数,如果遇到某个区间使得choice不在其里面,那就更新一下choice为当前这个区间的右端点,同时点的个数+ 1,按照这个步骤循环往复遍历所有区间… …

Code

#include <iostream>
#include <algorithm>
#define l first
#define r second
using namespace std;
typedef pair<int, int> PII;const int N = 1e5 + 10;PII R[N];
int n, choice, ans = 1;bool cmp(PII a, PII b){return a.r < b.r;
}int main(){scanf("%d", &n);for(int i = 0;i < n;i ++){int a, b;scanf("%d %d", &a, &b);R[i] = {a, b};}sort(R, R + n, cmp);        //每个区间按照右端点排序/*如果将每个区间的右端点作为被选中的那个点  那么对于后面的区间来讲,再需要新增的点的频率可能会降低首先选择第一个区间右端点*/choice = R[0].r;        for(int i = 1;i < n;i ++){if(R[i].l <= choice && choice <= R[i].r)            continue;       //这个区间被“照顾”到了  可以不用管了choice = R[i].r;        //这个区间跟前面的没有交集了  要更新右端点ans ++ ;        //多选择一个点}cout << ans << endl;return 0;
}

最大不相交区间数量

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

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

输入格式
第一行包含整数 NNN,表示区间数。

接下来 NNN 行,每行包含两个整数 ai,bia_i,b_iai,bi,表示一个区间的两个端点。

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

数据范围
1≤N≤105,1≤N≤10^5,1N105,
−109≤ai≤bi≤109−10^9≤a_i≤b_i≤10^9109aibi109

输入样例:

3
-1 1
2 4
3 5

输出样例:

2

关于这道题,其实在以前有一个很实际的例子介绍过:洛谷 P1803 - 凌乱的yyy / 线段覆盖。
那么仍然是右端点sort一遍,然后挨着找最多的不相交区间数量,其实可以注意到跟上题思路虽说不一样,但最终带来的结果却是一样的,因此完全可以用同样的代码(下面微调整了一下)。

Code

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;const int N = 1e5 + 10;struct ran{int l, r;bool operator< (const ran &t)const{return r < t.r;}
}Range[N];int n, ed;int main(){cin >> n;for(int i = 0;i < n;i ++){int a, b;cin >> a >> b;Range[i] = {a, b};}sort(Range, Range + n);int ans = 0, ed = -2e9;for(int i = 0;i < n;i ++)if(ed < Range[i].l){ans ++;ed = Range[i].r;}cout << ans << endl;return 0;
}

区间分组

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

输入格式
第一行包含整数 NNN,表示区间数。

接下来 NNN 行,每行包含两个整数 ai,bia_i,b_iai,bi,表示一个区间的两个端点。

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

数据范围
1≤N≤105,1≤N≤10^5,1N105,
−109≤ai≤bi≤109−10^9≤a_i≤b_i≤10^9109aibi109

输入样例:

3
-1 1
2 4
3 5

输出样例:

2

思路:按照左端点从小到大sort一遍,然后每组记录一个当前组内所有区间里最大的那个右端点值Max_r,方便后面的区间判断适不适合加入到这个组里来。也就是

  • 遍历每个区间,如果有某个组的Max_r < Range[i].l,说明该区间可以加到里面去,因此更新一下这个组的Max_rRange[i].r意味着已经加入了。
  • 由于可能有很多组都满足上面那个条件,只需任选一组就可以。
  • 如果不存在满足上面条件的组,那就需要为该区间“另起炉灶”新开一个组。

注意到:遍历每个区间是O(n)O(n)O(n)的,而在每个区间下遍历每个组又是O(n)O(n)O(n)的,所以复杂度就是O(n2)O(n^2)O(n2)的,显然对于10510^5105的数据量是会超时的,所以不妨使用小根堆优化找合适的组这一步,这样一来复杂度就优化至了O(nlogn)O(nlogn)O(nlogn)了。

  • 使小根堆存各个组的Max_r,取堆顶,如果最小的Max_r都不能满足Max_r < Range[i].l那就没有可以满足的了,直接“另起炉灶”;如果堆顶可以满足条件,那就放到堆顶这一组里。总而言之都能一步到位。

Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
#define l first
#define r secondconst int N = 1e5 + 10;PII ran[N];
priority_queue<int, vector<int>, greater<int>> heap;       //用小根堆存下每个组的Max_r
int n;int main(){cin >> n;for(int i = 0;i < n;i ++){int u, v;cin >> u >> v;ran[i] = {u, v};}sort(ran, ran + n);for(int i = 0;i < n;i ++){if(heap.empty())        heap.push(ran[i].r);else{int tt = heap.top();if(tt < ran[i].l){heap.pop();heap.push(ran[i].r);        //变相改变这个组的Max_r}else        heap.push(ran[i].r);}}cout << heap.size() << endl;return 0;
}

区间覆盖

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

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

输入格式
第一行包含两个整数 sssttt,表示给定线段区间的两个端点。

第二行包含整数 NNN,表示给定区间数。

接下来 NNN 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。

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

如果无解,则输出 −1

数据范围
1≤N≤105,1≤N≤10^5,1N105,
−109≤ai≤bi≤109,−10^9≤a_i≤b_i≤10^9,109aibi109,
−109≤s≤t≤109−10^9≤s≤t≤10^9109st109

输入样例:

1 5
3
-1 3
2 4
3 5

输出样例:

2

思路:按照左端点对区间sort一遍,然后

  1. 对于每个能包含住s(左限制端点)的区间,找到那个有最大r的区间,然后让这个r成为新的s(言外之意原来那个s已经被“照顾”了,现在的r才是新的需要考虑照顾的左限制端点),并让区间数ans ++
  2. 如果发现找到的r >= t,说明已经把整个要求的限制区间都囊括到了,break
  3. 如果发现找到的r < s,说明连左限制端点都囊括不到,答案不存在,break
  4. 下一次要关注的区间直接是有最大r的区间,并重复步骤1。

Code

#include <iostream>
#include <algorithm>
using namespace std;const int N = 1e5 + 10;struct Range{int l, r;bool operator < (const Range &t) const{return l < t.l;}
}ran[N];
int n, s, t;int main(){cin >> s >> t;cin >> n;for(int i = 0;i < n;i ++){int a, b;cin >> a >> b;ran[i] = {a, b};}sort(ran, ran + n);int ans = 0;bool flag = false;for(int i = 0;i < n;i ++){int ed = -2e9;      //ed作为找到的最大那个rint j = i;while(j < n && ran[j].l <= s){      //双指针寻找最大red = max(ed, ran[j].r);j ++;}if(ed < s){        //最大的右端点也不能包含到点s        注意用“<”因为可能s 等于 tbreak;}ans ++;i = -- j;          //循环跳转, -- j是因为上面while执行了一遍多余的j ++s = ed;if(ed >= t){flag = true;break;}}if(flag)        cout << ans << endl;else            cout << -1 << endl;return 0;
}

http://www.ppmy.cn/news/1896.html

相关文章

[网络工程师]-应用层协议-电子邮件协议

常见的电子邮件协议有简单邮件传输协议、邮局协议和Internet邮件访问协议。 1、简单邮件传输协议&#xff08;Simple Mail Transfer Protocol&#xff0c;SMTP&#xff09; SMTP主要负责将电子邮件从发送方传送到接收方&#xff0c;即对传输的规则做了规定&#xff0c;该协议工…

XX集团BIM项目解决方案

目 录 一、BIM发展现状 二、集团BIM建设总体规划&#xff08;建议&#xff09; 1、BIM实施目标 2、BIM实施的范围 3、BIM实施原则 4、集团BIM项目组织架构 4.1职能分配 4.2建模组织形式 4.3人员匹配建议 5、集团BIM应用功能架构 5.1 BIM平台对集团管理层面的价值 5…

[ vulhub漏洞复现篇 ] Apache Solr RemoteStreaming 文件读取与SSRF漏洞 (CVE-2021-27905)

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

[附源码]Python计算机毕业设计Django实验室管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Spring - FactoryBean扩展接口

文章目录Preorg.springframework.beans.factory.FactoryBeanFactoryBean中的设计模式----工厂方法模式FactoryBean VS BeanFactory源码解析扩展示例Pre Spring Boot - 扩展接口一览 org.springframework.beans.factory.FactoryBean package org.springframework.beans.factory…

【git 介绍】AhuntSun

Git应用详解第一讲&#xff1a;Git分区&#xff0c;配置与日志 Git应用详解第二讲&#xff1a;Git删除、修改、撤销操作 Git应用详解第三讲&#xff1a;本地分支的重要操作 Git应用详解第四讲&#xff1a;版本回退的三种方式与stash Git应用详解第五讲&#xff1a;远程仓库…

19-29-k8s-基本命令-yaml-kubectl

19-k8s-基本命令-yaml-kubectl&#xff1a; Kubernetes 集群的命令行工具kubectl 1、kubectl 命令格式&#xff1a; kubectl [command] [type] [name] [flags] 参数&#xff1a; command&#xff1a;指定要对资源执行的操作&#xff0c;例如create、get、describe、delete t…

Thinkpad x13 锐龙安装 Archlinux 记录

硬件配置&#xff1a; 笔记本影响cpu显卡内存硬盘ThinkPad X13 锐龙版r7 4750U核显16g1TB 山寨固态&#xff08;大华&#xff09;镜像准备 https://archlinux.org/download/ http://mirrors.163.com/archlinux/iso/2022.12.01/ 每次安装都检查iso镜像是否是网站最新的&#x…