贪心算法——区间覆盖问题

用于已知大线段和若干小线段的左右端点时,求最少的小线段可以将大线段完全覆盖

int n,m;//n个小线段,大线段的左右端点为1,m
struct op{
  int a,b;//小线段的左右端点
}tim[MAXN];
cin>>n>>m;
for(int i = 1;i <= n;++ i) cin>>tim[i].a>>tim[i].b;
int count = 0;
    int left = 1;
    while(left <= m){
        int mx = 0;
        for(int i = 1;i <= m;++ i)
            if(tim[i].a <= left)
                mx = max(mx,tim[i].b);
        count++;
        left = mx + 1;
    }
cout<<count;

我们稍加优化

可以发现我们只是在找比 \(left\) 小的左端点,这么找复杂度是 \(O(m)\) 的,那为什么不排个序直接 \(upper_bound log\) 的找呢,最大值求个前缀最大值就可以了

int n,m;
struct op{
  int a,b;
}tim[MAXN];
int d[MAXN],b[MAXN];
bool cmp(op x,op y) {return x.a<y.a;}
int main() {
    cin>>n>>m;
    for(int i = 1;i <= n;++ i) cin>>tim[i].a>>tim[i].b;
    sort(tim+1,tim+n+1,cmp);
    for(int i = 1;i <= n;++ i) {
        d[i] = max(d[i-1],tim[i].b);
        b[i] = tim[i].a;
    }
    int count = 0,left = 1;
    while(left <= m){
        int mx = 0;
        int pos = upper_bound(b+1,b+n+1,left)-b;
        if(pos+1==n+1) break;
        count++;
        left = mx + 1;
    }
    cout<<count;
    return 0;
}
posted @ 2022-06-06 10:58  双枫  阅读(146)  评论(0编辑  收藏  举报