区间问题
常见题型:线段覆盖等
常用策略:贪心
遇到这样的题时,考虑三种情况
- 相交(策略相关) 结合题目分析
------
-------
- 相离(常不考虑)
---- ----
- 包含(顺序相关) 考虑先处理哪个
---
---------
例题
luogu P2887【USACO07NOV】 防晒霜Sunscreen
题面:
有C个奶牛去晒太阳 ,每个奶牛各自能够忍受的阳光强度有一个最小值和一个最大值。
奶牛要涂抹防晒霜,防晒霜的作用是让阳光照在身上的阳光强度固定为某个值,为了不让奶牛烫伤,又不会没有效果。
给出L种防晒霜,每种的数量和固定的阳光强度。
每个奶牛只能抹一瓶防晒霜,最后问能够享受晒太阳的奶牛有几个。
S
o
l
u
t
i
o
n
Solution
Solution
把每只奶牛可忍受的光照强度看作区间(或线段)
对于这道题,排序函数可分按左端点排序,按右端点排序两种情况
以按右端点排为例
1.相交
---- 1
----- 2
此时若先处理1,则选防晒霜时应从小到大选;反之从大到小,按个人习惯选择
2.包含
--- 1
------- 2
选择多的2显然应该放下面
s o so so 排序函数为
il bool cmp(node x,node y){
return (x.r==y.r&&x.l<y.l)||(x.r<y.r);
}
C o d e Code Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#define re register
#define il inline
#define ll long long
using namespace std;
inline int read(){
int s=0,f=0;char c=getchar();
while(c<'0'||c>'9') f=(c=='-'),c=getchar();
while(c>='0'&&c<='9') s=(s<<3)+(s<<1)+(c^'0'),c=getchar();
return f?-s:s;
}
const int N=2505,M=1005;
int n,m,b[M],ans,now;
struct node{
int l,r;
}a[N];
/*
排序顺序
il bool cmp(node x,node y){ //左端点排序
return (x.l==y.l&&x.r<y.r)||(x.l>y.l);
}*/
il bool cmp(node x,node y){ //右端点排序(要分清左右端点!)
return (x.r==y.r&&x.l<y.l)||(x.r<y.r);
}
int main(){
n=read(),m=read();
for(re int i=1;i<=n;++i) a[i].l=read(),a[i].r=read();
for(re int i=1,x,y;i<=m;++i) x=read(),y=read(),b[x]+=y; //+= 可能重复
sort(a+1,a+n+1,cmp);
for(re int i=1;i<=n;++i)
/* for(re int j=a[i].r;j>=a[i].l;--j) */
for(re int j=a[i].l;j<=a[i].r;++j)
if(b[j]){ans++,b[j]--;break;}
printf("%d\n",ans);
return 0;
}
很少的一点个人理解
没有对贪心的证明,只想说一说排序的顺序
有点水