保研机试训练Day-30

贪心

Posted by Jeffzzc on April 22, 2025

贪心

区间选点

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

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

#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(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        int l,r;
        scanf("%d%d",&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;
        }
  
    printf("%d\n",res);
    return 0;
}

最大不相交区间数量

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

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

#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(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        int l,r;
        scanf("%d%d",&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;
        }
  
    printf("%d\n",res);
    return 0;
}

区间分组

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

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdio>
using namespace std;

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

int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        int l,r;
        scanf("%d%d",&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++){
        if(heap.empty() || heap.top() >= range[i].l){
            heap.push(range[i].r);
        }
        else{
            heap.pop();
            heap.push(range[i].r);
        }
    }
    printf("%d\n", heap.size());
    return 0;
}

区间覆盖

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

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

思路:

1.将所有区间按照左端点从小到大进行排序

2.从前往后枚举每个区间,在所有能覆盖start的区间中,选择右端点的最大区间,然后将start更新成右端点的最大值

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

using namespace std;
const int N = 100010;
int s,t;
int n;
struct Range{
    int l,r;
    bool operator< (const Range &w)const{
        return l < w.l;
    }
}range[N];


int main(){
    scanf("%d%d",&s,&t);
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        int l,r;
        scanf("%d%d",&l,&r);
        range[i]={l,r};
    }
    sort(range, range + n);
    int ans = 0;
    bool win = false;
    for(int i=0;i<n;i++){
        int j=i, r = -2e9;
        while(j < n && range[j].l <= s){
            r = max(r, range[j].r);
            j++;
        }
        if(r < s){
            ans = -1;
            break;
        }
        ans++;
        if(r >= t){
            win = true;
            break;
        }
        s = r;
        i = j - 1;
    }
    if(!win) ans = -1;
    printf("%d\n",ans);
    return 0;
}