题目链接:http://poj.org/problem?id=3614
题意:C头牛去晒太阳,每头牛有自己所限定的spf安全范围[min, max];有L瓶防晒液,每瓶有自己的spf值和容量(能供几头牛用)。
求这L瓶防晒液最多能让多少头牛安全地晒太阳。
思路:贪心策略,按spf从小到大或从大到小的顺序取出防晒液,供给尽可能多的剩余的牛。
具体如何判断当前这瓶防晒液最多能供给几头牛呢?
以spf从小到大排序所有防晒液为例,可以维护一个小顶堆,每取出一瓶防晒液l,就把剩余的所有min值低于l.spf的牛的max值放入堆中。
接下来在l的容量尚未耗尽时,反复弹出并比较堆顶值与l.spf,若大于l.spf,则 l 消耗1单位的容量供给这头牛,计数值加1;否则这头牛不能被任何防晒液供给(当前spf已经是剩余的最小值,后续不会有更小的)。反复取堆顶元素直至容量耗尽或堆变空。各瓶防晒液的计数值的总和即为答案。
首先需要将防晒液按spf值从小大到排序(O(LlogL)),以及将牛按min值从小到大排序(O(ClogC));然后外层循环对L瓶防晒液进行一遍扫描(O(L)),内层循环每头牛的max必然入堆一次、弹出一次(Ω(C)),所以总的复杂度为O(LlogL + CLogC + LC)。
自己实现的堆,时间上总是比STL的priority_queue慢一些,不过空间更少。
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 const int MAX_C = 2505; 5 const int MAX_L = 2505; 6 int C, L; 7 struct Cow 8 { 9 int min, max; 10 Cow& operator = (Cow& c){ 11 min = c.min; 12 max = c.max; 13 return *this; 14 } 15 }cows[MAX_C]; 16 17 struct Lotion 18 { 19 int spf,cover; 20 }lotions[MAX_C]; 21 22 bool cmpL(Lotion l1, Lotion l2){ 23 return l1.spf < l2.spf; 24 } 25 bool cmpC(Cow c1, Cow c2){ 26 return c1.min < c2.min; 27 } 28 29 int heap[MAX_C]; //小顶堆 30 int size = 0; 31 32 void swap(int& x, int& y){ 33 int tmp = x; 34 x = y; 35 y = tmp; 36 } 37 38 void insert(int x){ 39 size++; 40 heap[size-1] = x;//目标元素暂时插到末尾 41 int i = size - 1;//候选目标位置 42 while(i > 0){ //上滤,反复与父节点比较 43 int p = (i-1)/2; 44 if(heap[p] > heap[i]){//与父节点违反堆序性时 45 swap(heap[i], heap[p]);//父节点下沉 46 i = p; //候选位置攀升 47 }else break; 48 } 49 } 50 51 void deleteTop(){ 52 heap[0] = heap[size-1]; 53 size--; 54 int i = 0; //候选目标位置 55 while(i*2+1 < size){//下滤 56 int lc = i*2+1; 57 int rc = i*2+2; 58 int c = lc; 59 if(rc<size && heap[rc]<heap[lc]) 60 c = rc; 61 if(heap[c] < heap[i]){ 62 swap(heap[c], heap[i]);//孩子节点攀升 63 i = c;//候选位置下沉 64 }else break; 65 } 66 } 67 68 int getTop(){ 69 return heap[0]; 70 } 71 72 int main() 73 { 74 freopen("3614.txt", "r", stdin); 75 scanf("%d%d", &C, &L); 76 for(int i=0; i<C; i++){ 77 scanf("%d%d", &cows[i].min, &cows[i].max); 78 } 79 80 for(int i=0; i<L; i++){ 81 scanf("%d%d", &lotions[i].spf, &lotions[i].cover); 82 } 83 84 sort(lotions, lotions+L, cmpL); 85 sort(cows, cows+C, cmpC); 86 87 int cnt = 0; 88 for(int i=0, j=0; i<L; i++){ 89 //printf("lotion %d %d\n", lotions[i].spf, lotions[i].cover); 90 while(j<C && cows[j].min <= lotions[i].spf){ 91 insert(cows[j].max); 92 j++; 93 //printf("insert %d\n", cows[j-1].max); 94 } 95 int vol = lotions[i].cover; 96 97 while(vol > 0 && size>0){ 98 if(getTop() >= lotions[i].spf){ 99 vol--; 100 cnt++; 101 //printf("add %d\n", getTop()); 102 } 103 deleteTop(); 104 //printf("%d\n", cnt); 105 } 106 } 107 printf("%d\n", cnt); 108 return 0; 109 }