前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >算法基础-贪心

算法基础-贪心

作者头像
她的店里只卖樱花
发布2022-10-31 16:39:11
4680
发布2022-10-31 16:39:11
举报
文章被收录于专栏:常用算法模板

区间问题

01.区间选点

题目描述

给定 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

输入样例:
代码语言:javascript
复制
3
-1 1
2 4
3 5
输出样例:
代码语言:javascript
复制
2

题解

时间复杂度

O(nlogn)

证明:

  1. 证明ans$$\le$$cntcnt 是一种可行方案, ans是可行方案的最优解,也就是最小值。
  2. 证明ans$$\ge$$cntcnt可行方案是一个区间集合,区间从小到大排序,两两之间不相交。

所以覆盖每一个区间至少需要cnt个点。

核心思想

  1. 将每个区间按照右端点从小到大进行排序
  2. 从前往后枚举区间,end值初始化为无穷小
    • 如果本次区间不能覆盖掉上次区间的右端点, ed < range[i].l
    • 说明需要选择一个新的点, res ++ ; ed = range[i].r;

核心函数

代码语言:javascript
复制
sort(nodes, nodes + n);
   	int res = 0, ed = -2e9;
   	for(int i = 0; i < n; i ++)
   		if(nodes[i].l > ed)
   		{
   			res ++ ;
   			ed = nodes[i].r;
   		}

代码实现

代码语言:javascript
复制
/**********************************************
*             她的店里只卖樱花                  *
***********************************************/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <unordered_map> 
#include <queue>
using namespace std;
#define fi first
#define se second
#define _for(i,b) for(int i=(0);i<(b);i++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,b,a) for(int i=(b);i>=(a);i--)
#define mst(abc,bca) memset(abc,bca,sizeof abc)
#define ios_op cin.tie(0), cout.tie(0), ios::sync_with_stdio(0);
#define endl '\n'
#define sendl " \n"
typedef priority_queue<int, vector<int>, greater<int> > PQ;
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

const int Inf = 0x3f3f3f3f, Null = 0x80808080;
const double eps=1e-6;
const double PI=acos(-1.0);
const int MOD = 1e9 + 7;
const int N = 100010;
int n;

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

template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
  while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

template <typename T> void print(T x) {
    if (x < 0) { putchar('-'); print(x); return ; }
    if (x >= 10) print(x / 10);
    putchar((x % 10) + '0');
}

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-04-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 区间问题
    • 01.区间选点
      • 题目描述
      • 题解
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档