• B. The Walkway Codeforces Round 893 (Div. 2)


    Problem - B - Codeforces

    题目大意:小明在数轴上要从1走到n,其中某些坐标上有一些饼干店,共m个,小明身上也有无限多的饼干,它首先一定会在1的位置吃一个饼干,在每个饼干店的位置会吃一个,在前d个位置没有吃饼干(加入当前位置为i,在[i-d+1,i]之间没有吃饼干),就会吃一个,以上三种情况如果有某些同时发生,只会吃一个,现在要求移除一个商店,问小明吃的最少的饼干数是多少,且满足这个饼干数的方案有多少种

    2<=n<=1e9;2<=m<=min(1e5,n)

    思路:要知道移除哪些商店最好,只能是枚举每个商店,维护移除该商店前和移除后的饼干数,移除前的饼干数,直接用原始的数组求,我们在位置1的位置吃一个,然后对于第一个商店,产生的贡献就是(a[i]-1)/d,向上取整,对于后面的每个商店,因为前一个商店已经算过了,所以产生的贡献就是(a[i]-a[i-1])/d,向上取整,这样就算出了初始不移除商店的饼干数

    接下来枚举每个商店,先用总贡献减去这个商店的贡献,先减去自身的1,然后减去前一部分也就是(a[i]-a[i-1]/d),因为不能重复减去这个商店的贡献,所以如果是整除的话,要再+1,然后减去后一部分(a[i+1]-a[i])/d,因为不能减去右边商店的贡献,所以如果整除也要+1。然后再加上移除这个商店后,i-1和i+1之间的贡献,也就是(a[i+1]-a[i-1])/d,同理因为不能算边界,所以如果整除要-1。

    之后就得到了每个商店移除前后的饼干数,维护最小值并统计最小值数量即可

    1. #include
    2. //#include<__msvc_all_public_headers.hpp>
    3. using namespace std;
    4. typedef long long ll;
    5. const int N = 1e5 + 5;
    6. const int INF = 0x7fffffff;
    7. const ll MOD = 998244353;
    8. int n;
    9. ll a[N];
    10. void init()
    11. {
    12. }
    13. void solve()
    14. {
    15. cin >> n;
    16. init();
    17. ll m, d;
    18. cin >> m >> d;
    19. a[m + 1] = n;//方便处理边界
    20. for (int i = 1; i <= m; i++)
    21. {
    22. cin >> a[i];
    23. }
    24. ll cnt = 0;
    25. for (int i = 1; i <= m; i++)
    26. {
    27. if (i == 1 && a[i] != 1)
    28. cnt++;//先处理位置1,之后就不用管左边界了
    29. cnt += (a[i] - a[i - 1] - 1) / d + 1;//记录原始数组的总饼干数
    30. }
    31. if(a[m]!=n)
    32. cnt += (n - a[m]) / d;//特判n的位置有没有处理过
    33. ll micnt = cnt;
    34. ll cntans = 0;
    35. for (int i = 1; i < m; i++)
    36. {
    37. ll temp = cnt - 1;//移除这个商店后的饼干数
    38. temp -= (a[i] - a[i - 1]) / d;//先减去这个歌商店原来的贡献
    39. if ((a[i] - a[i - 1]) % d == 0)
    40. {
    41. temp++;
    42. }
    43. temp -= (a[i+1] - a[i]) / d;
    44. if ((a[i+1] - a[i]) % d == 0)
    45. {
    46. temp++;
    47. }
    48. temp += (a[i + 1] - a[i - 1]) / d;//加上这个区间新的贡献
    49. if ((a[i + 1] - a[i - 1]) % d == 0)
    50. {
    51. temp--;
    52. }
    53. if (temp < micnt)
    54. {
    55. micnt = temp;//维护最小值
    56. cntans = 1;//维护最小值数量
    57. }
    58. else if (temp == micnt)
    59. {
    60. cntans ++ ;
    61. }
    62. }
    63. ll temp = cnt - 1;
    64. temp -= (a[m] - a[m - 1]) / d;//因为最后一个商店没有右边的商店,所以单独处理一下
    65. if ((a[m] - a[m - 1]) % d == 0)
    66. {
    67. temp++;
    68. }
    69. temp -= (a[m + 1] - a[m]) / d;
    70. temp += (a[m + 1] - a[m - 1]) / d;
    71. if (temp < micnt)
    72. {
    73. micnt = temp;
    74. cntans = 1;
    75. }
    76. else if (temp == micnt)
    77. {
    78. cntans++;
    79. }
    80. cout << micnt << " " << cntans << endl;
    81. }
    82. int main()
    83. {
    84. cin.tie(0);
    85. cout.tie(0);
    86. ios::sync_with_stdio(false);
    87. int t;
    88. cin >> t;
    89. a[0] = 1;
    90. while (t--)
    91. {
    92. solve();
    93. }
    94. return 0;
    95. }

  • 相关阅读:
    如何打造一支专业的QA团队,至少要关注这5点
    Java基础知识点整理
    技术管理进阶——跨级管理/汇报
    【CodeTop】20. 有效的括号
    Java内存空间(学习随笔)
    【Flink】 FlinkCDC读取Mysql( DataStream 方式)(带完整源码,直接可使用)
    Map集合中,当添加一个键值对元素时,HashMap发生了什么?
    膀胱结石的危害是怎么样的?
    vue前端项目配置
    Android Fragment 基本概念和基本使用
  • 原文地址:https://blog.csdn.net/ashbringer233/article/details/132688358