线段覆盖一类的贪心
统一思路:先对右端点进行排序,尝试维护最优子结构(取最差的)
实在不行对左端点排序
区间完全覆盖问题
给定一个长度为m的区间,再给出n条线段的起点和终点(注意这里是闭区间)
求最少使用多少条线段可以将整个区间完全覆盖
- 对右端点进行从大到小排序,每次选最小的左端点进行更新
最大不相交覆盖
给定一个长度为m的区间和n条线段的起点和终点,
从中选取尽量多的线段,使得线段都是互不相交的
- 对右端点进行从小到大排序,每次操作保证线段条数最多且右端点最小
- 按右端点排序后,可以考虑DP
区间选点问题
给定一个长度为m的区间,n条线段和这n条线段上至少有多少点
整个区间内最少选择几个点,使其满足每一条线段的要求.
- 按右端点从小到大排序,如果右端点相同按左端点排序,依次加点
- 可以对前缀和数组进行差分后差分约束系统
Luogu P2887 [USACO07NOV]Sunscreen G
有C个奶牛去晒太阳 (1 <=C <= 2500),每个奶牛各自能够忍受的阳光强度有一个最小值和一个最大值。
奶牛就得涂抹防晒霜,防晒霜的作用是让阳光照在身上的阳光强度固定为某个值。
给出了L种防晒霜。每种的数量和固定的阳光强度也给出来了
每个奶牛只能抹一瓶防晒霜,最后问能够享受晒太阳的奶牛有几个。
- 抽象模型:存在若干线段和若干点,每条线段只能覆盖一个点,问最多能覆盖多少点
按右端点从小到大排序,每次选距离左端点最近的点(即最差情况)
#include<bits/stdc++.h>
using namespace std;
const int N=3005;
int n,m,b[N],ans;
struct A{int a,b; }a[N];
bool cmp(A i,A j) {
return i.b<j.b;
}
set<int>s;
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {
scanf("%d%d",&a[i].a,&a[i].b);
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=m;i++) {
int x,y; scanf("%d%d",&x,&y);
b[x]+=y;
}
for(int i=1;i<=1000;i++){
if(b[i]) s.insert(i);
}
for(int i=1;i<=n;i++) {
auto t=s.lower_bound(a[i].a);
if(t!=s.end()&&*t<=a[i].b) {
b[*t]--;
if(b[*t]==0) s.erase(t);
ans++;
}
}
printf("%d\n",ans);
return 0;
}

浙公网安备 33010602011771号