【 贪心 进阶总结 】【 来自一本通提高篇 】

#10000. 「一本通 1.1 例 1」活动安排

区间与区间的最大不覆盖数—套板子(区间右端点从小到大排序,选择不冲突的,尽可能的选)简记为线段覆盖问题

#10001. 「一本通 1.1 例 2」种树

区间内最少单点满足覆盖要求,不管是各个区间需要一个点还是一个子区间(这个子区间是可连续、可不连续的)

按照区间右端点从小到大排序,依次满足各个区间的要求,如此下来种的树(需要的点)最少。

如果想不出贪心,线段树+优化亦可作。

#10002. 「一本通 1.1 例 3」喷水装置

选择尽量少的区间覆盖指定线段区间。

【 模板 】将所有的区间按照左端点从小到大排序,对于当前查找的起点s ,选择覆盖点 s 的区间中右端点中最大的一个,并将 s 更新为此区间的右端点,(这样区间数目+1)直到s>=整个线段长度。(在s时刻,找一个左端点小于等于s的最大右端点)

对于这道题,需要进行一些转化——每个浇灌喷头受限于所能喷到的最短距离,它的最短距离是半径到达草坪上端。此时,如果将整个草坪长度想象为 x轴的正半轴,那么,我们应该根据勾股定理找到水平距离,即(\sqrt{r^{2}-(\frac{W}{2})^{2}})。把当前点的pos减去水平距离作为左端点,pos+水平距离作为右端点。然后就是套上面的板子↑。

PS:一定要理解了过程再写,一定要理解了过程再写,一定要理解了过程再写!!!

附上AC代码:

#include 
#include 
#include 
#include 
#define N 300005

using namespace std;

const double Eps = 1e-5 ;

inline int wread(){
    char c=getchar ();int flag=1,wans=0;
    while (c<'0'||c>'9'){if (c=='-') flag=-1;c=getchar ();}
    while (c>='0'&&c<='9'){wans=wans*10+c-'0';c=getchar ();}
    return wans*=flag;
}

int T;
int n,L,W;
struct node {double lx,rx;int pos,r;}a[N];
bool e666 (node x,node y){return x.lx=re)	s=max(s,a[nx].rx);
				nx++;
			}
			if (s>=L)	{break;}
			if (re==s)	{F=false;break;}//未更新,请画图____即当前区间与下个区间之间 一定有一段距离,不符合全部覆盖的要求,退出 
		}
		if (!F)	puts("-1");
		else	printf("%d\n",ans);
	}
	return 0;
}

未完待续...

你可能感兴趣的:(巧妙题,贪心)