题目:http://codeforces.com/problemset/problem/746/F
先感叹一下题目之长!
一些测试样例在后面给出。
题目大意:
Sasha 去工作的路上喜欢听歌,途中经历 K 分钟,有一个歌单,顺序播放。
每首歌都对应一个开心值 ai ,持续时间为 ti 分钟
开始的时候先选定一首歌曲,例如第x首,从这首歌开始顺序播放,终止条件为:歌单播放完或行程到终点了
一首歌可以播放整首或只播放一部分,后者必须播放歌曲的一半时间(取上整)以上才能获得对应的开心值。
播放一部分还有一个曲目数量限制为w,只有w首歌曲支持半曲播放。
问:确定n w k 的情况下,Sasha能够获取的最大开心值。
思路:
设定两个set 容器,一个存整首曲目,一个存半曲曲目。想要在固定的时间K 之内听更多的歌曲开心值更高,而且必须是连续的曲目,那就要把时间长的尽量折半,把时间短的让出来按整首去听。所以,刚开始都先把歌曲按半曲存,如果半曲列表满了之后,再根据情况选择性弹出,替换。当K 时间用完之后,就从左边开始删歌曲,保证后面遍历完所有的情况,因为,可以从中任何一首歌曲开始听。这样求取过程中产生的最大开心值即可。半曲列表最大容量为w,原来用的加法做,感觉有点复杂,后来改了减法,这个看个人喜好。
代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<set> 4 using namespace std; 5 int arr[200005]; 6 int happy[200005]; 7 8 inline long max(long x, long y) 9 { 10 return x > y ? x : y; 11 } 12 13 int main() 14 { 15 long N, W, K; 16 while (scanf("%ld %ld %ld", &N, &W, &K) != EOF) 17 { 18 long result = 0, RESULT = 0; 19 set<pair<int, int> >S_, S; //分别代表半曲容器和整首容器 20 for (int i = 1; i <= N; ++i) 21 scanf("%d", happy + i); 22 for (int i = 1; i <= N; ++i) 23 scanf("%d", arr + i); 24 int l, r; 25 l = r = 1; 26 while (r <= N) 27 { 28 //right pointer; 29 while (r <= N) 30 { 31 if (W) 32 { 33 if (K >= (arr[r] + 1) / 2) 34 { 35 K -= (arr[r] + 1) / 2; 36 RESULT = max(RESULT, result += happy[r]); 37 S_.insert(make_pair(arr[r], r)); 38 r++; 39 W--; 40 } 41 else break; //行程结束 42 } 43 else //如果w位置已满 44 { 45 int tmp = S_.begin()->first; 46 if (tmp <= arr[r] && K >= (arr[r] + 1) / 2 - (tmp + 1) / 2 + tmp) //如果当前的比半曲列表中时间最短的花费时间长,替换 47 { 48 K -= (arr[r] + 1) / 2 - (tmp + 1) / 2 + tmp; 49 RESULT = max(RESULT, result += happy[r]); 50 auto p = S_.begin(); 51 S.insert(*p); 52 S_.erase(p); 53 S_.insert(make_pair(arr[r], r)); 54 r++; 55 } 56 else if (tmp > arr[r] && K >= arr[r]) //如果当前的比半曲列表中时间最短的还短,那么就把当前的短歌放入S 57 { 58 K -= arr[r]; 59 RESULT = max(RESULT, result += happy[r]); 60 S.insert(make_pair(arr[r], r)); 61 r++; 62 } 63 else break; 64 } 65 } 66 //left pointer; K时间已经满了,从左边开始删除歌曲,以保证继续往后遍历 67 if (l < r) 68 { 69 if (S.find(make_pair(arr[l], l)) != S.end()) 70 { 71 K += arr[l]; 72 result -= happy[l]; 73 S.erase(make_pair(arr[l], l)); 74 } 75 else 76 { 77 K += (arr[l] + 1) / 2; 78 result -= happy[l]; 79 S_.erase(make_pair(arr[l], l)); 80 W++; 81 if (!S.empty()) 82 { 83 auto p = --S.end(); 84 K += p->first - (p->first + 1) / 2; 85 S_.insert(*p); 86 W--; 87 S.erase(p); 88 } 89 } 90 l++; 91 } 92 else l++, r++; 93 } 94 printf("%d ", RESULT); 95 } 96 }
Sample Input
6 4 10 2 4 5 20 4 8 6 3 5 20 8 7 6 4 10 7 7 8 20 3 7 6 3 5 20 8 7 5 3 12 20 2 1 2 3 16 6 2 4 3
Sample Output
20 22 23
感谢您的阅读,生活愉快~