【BZOJ】1828: [Usaco2010 Mar]balloc 农场分配(经典贪心)

【算法】贪心+线段树

【题意】给定n个数字ci,m个区间[a,b](1<=a,b<=10^5),每个位置最多被ci个区间覆盖,求最多选择多少区间。

附加退化问题:全部ci=1,即求最多的不相交的区间。

【题解】本题是区间和点之间的经典贪心,有两种经典做法,本质思想都是通过排序实现扫描线,细节根据题目不同而不同。

一、从区间角度出发,按区间右端点从小到大排序

然后再按左端点从大到小排序,从左到右能加就加。

感性理解:在对右影响一致的情况下,选择对左影响最小的。

证明:假设有最优决策序列S和当前决策序列P,对于S中选择了的区间[a,b](a之前的不再考虑),由于同一右端点能选就选,所以在P中和[a,b]对应的区间[c,d]满足d<=b。

如果d<a,则P优于S。

如果a<=d<b,则在1~d答案一致的情况下,S还给[d+1,b]减一,P优于S。

如果d=b,则P和S一致。

过程中由于a之前不再考虑,不再详细讨论左端点的情况。

从而P不劣与S,证毕。

这是贪心证明的经典过程。

然后用线段树维护区间减和区间最小值。

程序,留坑。

 

二、从点的角度出发,按区间左端点排序。

每个点需要选择ci个线段,在对左影响相同(左边点都满足了)的情况下,选择右端点偏左的。

具体实现方式:用维护当前节点的线段,一个线段入堆只在其左端点处就可以了,提前算一下每个点的线段覆盖数(只记差分,过程中边算边算前缀和)。

posted @ 2017-09-22 12:58  ONION_CYC  阅读(345)  评论(0编辑  收藏  举报