• 2023 Shandong Provincial Collegiate Programming Contest


    D. Fast and Fat(2023 ICPC 山东省赛)(二分+贪心检查)

    题意:

            对于一个运动员 i ,他的速度是 vi,体重是 wi。如果运动员 j 的体重 wj <= wi,那么运动员 i 可以用原本的速度 vi 背着运动员 j 奔跑。如果 wj > wi,那么速度就变成了 vi - ( wi - wj ) (如果是负数,那么运动员 i 不能背着 j 奔跑)。

            给定一个T,代表有T组数据。每组数据第一行输入一个n,代表这个团队有n个人,后面n行,每行两个数vi,wi。运动员可以被背着跑,也不能不背着人跑。求这个团队奔跑起来后速度最慢的那个人  的速度最大值

    思路:

            我们可以发现,当vi+wi > vj+wj 时,i 一定可以背着 j 跑。

            考虑取速度最大值和最小值,然后不断二分找答案。

            在二分答案时,对于答案 x ,选出大于等于速度 x 的人当中 vi+wi 最高的几个人,分别去背着速度小于 x 的人当中 wi 最大的人奔跑。

    代码:

    1. #include
    2. using namespace std;
    3. const int N = 1e5+5;
    4. #define int long long
    5. typedef pair<int, int>PII;
    6. const int Max = 0x3f3f3f3f3f3f3f3f;
    7. const int Min = -0x3f3f3f3f3f3f3f3f;
    8. int n, m, k;
    9. int T;
    10. PII q1[N], q2[N];
    11. queue<int>que, que2;
    12. bool cmp(PII aa, PII bb)
    13. {
    14. return aa.first+aa.second > bb.first+bb.second;
    15. }
    16. bool cmp2(PII aa, PII bb)
    17. {
    18. return aa.second > bb.second;
    19. }
    20. int check(int x)
    21. {
    22. while(que.size()) que.pop(); //多组输入,每次使用队列前都要清空
    23. while(que2.size()) que2.pop();
    24. //如果速度大于等于当前 x,那么将vi+wi从大到小存入队列(已经排完序了)
    25. for(int i = 0; i < n; i ++)
    26. {
    27. if(q1[i].first>=x) que.push(q1[i].first + q1[i].second - x);
    28. }
    29. //如果速度小于当前的 x, 那么将wi从大到小存入队列
    30. for(int i = 0; i < n; i ++)
    31. {
    32. if(q2[i].firstpush(q2[i].second);
    33. }
    34. //如果可以背人的人数小于需要被人背着的人数,直接false
    35. if(que.size() < que2.size()) return false;
    36. //一一对应,队列中vi+wi最大的去背着队列中wi最大的,队列中vi+wi第二大的去背着队列wi第二大的...
    37. while(que2.size())
    38. {
    39. if(que.front() < que2.front()) return false;
    40. que.pop(), que2.pop();
    41. }
    42. return true;
    43. }
    44. signed main()
    45. {
    46. ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    47. cin >> T;
    48. while(T --)
    49. {
    50. int head = Min, tail = Max;
    51. cin >> n;
    52. for(int i = 0; i < n; i ++)
    53. {
    54. int x, y;
    55. cin >> x >> y;
    56. q1[i].first = q2[i].first = x;
    57. q1[i].second = q2[i].second = y;
    58. head = max(x, head); //求出速度的最大值和最小值
    59. tail = min(x, tail);
    60. }
    61. sort(q1, q1+n, cmp); //pair 排序(根据vi+wi从大到小)
    62. sort(q2, q2+n, cmp2); // 根据wi从大到小排序
    63. // 二分答案
    64. while(tail < head)
    65. {
    66. int mid = head + tail + 1 >> 1;
    67. if(check(mid)) tail = mid;
    68. else head = mid - 1;
    69. }
    70. cout << head << "\n";
    71. }
    72. return 0;
    73. }

  • 相关阅读:
    show processlist 详解
    醛肽:Gly-Phe-Gly-aldehyde、102579-48-6
    C++学习——vector类的使用
    Xcode13 “消失”的Info.plist文件
    mysql的索引语法
    java计算机毕业设计咖啡屋订单系统源码+mysql数据库+系统+lw文档+部署
    12【module的语法】
    内存函数 memcpy 和 memmove 的讲解和模拟实现
    scipy 窗函数进行设计FIR滤波器
    事务管理需要了解的前置知识
  • 原文地址:https://blog.csdn.net/RGHLY21/article/details/133754273