AcWing 905. 区间选点 贪心

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

输出选择的点的最小数量。位于区间端点上的点也算作区间内。

输入格式

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

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

输出格式

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

数据范围

1≤N≤105,
−109≤ai≤bi≤109

输入样例:
3
-1 1
2 4
3 5
输出样例:
2

可以使用贪心解决。

    将区间按右端点排序

    遍历区间,如果该区间中不包含最后选的那个点,则选取区间右端点。如果包含最后选的那个点,则跳过。

    输出所选点的个数。

证明

假设最优解为 ans 个点,贪心算法求出的为 cnt 个点。 只需要证明 ans == cnt 即可。

因为 ans 是最优解,所以 ans <= cnt。

贪心算法求出的结果为 cnt,每次让选取点数+1的区间一定不相交。共计cnt个这样的区间。,为了覆盖这cnt个区间, 至少需要cnt个点。所以ans >= cnt。

综上: cnt == ans

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int N  = 100010;
//保存区间
vector<vector<int>> a(N,vector<int>(2,0));
int n;

int main()
{
    cin >> n;
    //读入区间
    for(int i = 0; i< n; i++)
    {
        int l, r;
        cin >> l >> r;
        a[i][0] = l;
        a[i][1] = r;
    }
    // 按右端点排序
    sort(a.begin(), a.begin() + n, [](vector<int> &a, vector<int> &b){return a[1] < b[1];});
    // res 保存答案,end 是当前选的点
    int res = 0, end = -1e9 - 10;
    // 遍历区间
    for(int i = 0; i < n; i++)
    {
        // 如果当前选的点覆盖了该区间,则跳过
        if(end >= a[i][0] && end <= a[i][1]) 
            continue;
        else
        {
            // 选的点+1, 选的点更新为区间右端点
            res++;
            end = a[i][1];
        }
    }
    cout << res;
    return 0;
}


#include<iostream>
#include<algorithm>
#include<cstring>

using  namespace std;

const int N=1e5+10;

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

int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        ranges[i]={l,r};
    }
    sort(ranges,ranges+n);
    int res=0,st=-2e9;
    for(int i=0;i<n;i++)
    {
        if(st<ranges[i].l)
        {
            res++;
            st=ranges[i].r;
        }
    }
    cout<< res <<endl;
    return 0;
}

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 1e5 + 10;

struct Range
{
    int l, r;
} ranges[N];

bool compareRanges(const Range &a, const Range &b)
{
    return a.r < b.r;
}

int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        int l, r;
        scanf("%d%d", &l, &r);
        ranges[i].l = l; ranges[i].r = r;
    }
    sort(ranges, ranges + n, compareRanges);
    int res = 0, st = -2e9;
    for (int i = 0; i < n; i++)
    {
        if (st < ranges[i].l)
        {
            res++;
            st = ranges[i].r;
        }
    }
    cout << res << endl;
    return 0;
}

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值