• Music in Car CF 746F


    题目: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

    感谢您的阅读,生活愉快~

  • 相关阅读:
    常见设计模式,总结的不错(转)
    mysql查询当前时间,一天内,一周,一个月内的sql语句
    PBOC金融IC卡,卡片与终端交互的13个步骤,简介-第一组(转)
    金融IC卡 ARQC和ARPC计算方法和实例(转)
    如何解决结果由block返回情况下的同步问题(转)
    linux进程编程:子进程创建及执行函数简介
    exec函数族实例解析
    C语言中system()函数的用法总结(转)
    关于JSPatch热修复
    做个这样的APP要多久?[转]
  • 原文地址:https://www.cnblogs.com/lv-anchoret/p/8461705.html
Copyright © 2020-2023  润新知