贪心算法——区间覆盖问题
用于已知大线段和若干小线段的左右端点时,求最少的小线段可以将大线段完全覆盖
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;
}