区间问题贪心策略 个人分析

区间问题
常见题型:线段覆盖等
常用策略:贪心
遇到这样的题时,考虑三种情况

  1. 相交(策略相关) 结合题目分析
------
   -------  
  1. 相离(常不考虑)
----   ----
  1. 包含(顺序相关) 考虑先处理哪个
   ---   
---------

例题
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
#include
#include
#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.ry.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;
}

很少的一点个人理解
没有对贪心的证明,只想说一说排序的顺序
有点水

你可能感兴趣的:(算法,贪心,区间)