• C. Zero-Sum Prefixes Codeforces Round #833 (Div. 2)(前缀和+贪心)


    传送门

    题意:

    给你一个长度为n的数组,里面包含a1,a2,a3...an  n个元素,

    a_i=0的时候,你可以将a_i变成任意数字,

    问你经过任意次操作后对于1<=i<=n,它的前i项和为0的个数是最大是多少?

    思路:

    假设数组一个0都没有的话:那么结果就是前缀和为0的个数。

    如果只有一个0的话:那么因为改变0的值并不会改变他前面的元素的前缀和,所以对于0前面的元素res1为前半部分前缀和为0的个数:

    对于后半部分因为0可以改变成任意数字,那么可以将它变成0(包括0)之后的前缀和出现次数最多的的元素的负这样可以产生出最多的前缀和为0的值res2。

    最后结果就是res1+res2

    如果有两个0的话,前半部分同理依旧是res1;对于两个0中间的情况,因为第一个0改变值产生的影响对后面的元素的值的改变是一样的,那么就是说无论第一个0怎么改变,都不会影响第二个0的最优数量。那么就是从第一个0(包括)到第二个0(不包括)之间的前缀和出现次数最多的结果res2,之后再加上最后一个0到末尾的前缀和出现次数最多的结果res3,res1+res2+res3就是当前情况的结果。

    那么综合分析:对于还没有出现0的区域,这部分的答案就是前缀和为0的数量,之后每次从第一个0开始,到第二个0,找出出现元素次数最多的数量并加上,直到最后一个0到n的(也可以额外加个0在n+1的位置)结果总和加起来就是最优的情况。

    1. /**
    2. *  ┏┓   ┏┓+ +
    3. * ┏┛┻━━━┛┻┓ + +
    4. * ┃       ┃
    5. * ┃   ━   ┃ ++ + + +
    6. * ████━████+
    7. * ◥██◤ ◥██◤ +
    8. * ┃   ┻   ┃
    9. * ┃       ┃ + +
    10. * ┗━┓   ┏━┛
    11. *   ┃   ┃ + + + +Code is far away from  
    12. *   ┃   ┃ + bug with the animal protecting
    13. *   ┃    ┗━━━┓ 神兽保佑,代码无bug 
    14. *   ┃       ┣┓
    15. *   ┃        ┏┛
    16. *  ┗┓┓┏━┳┓┏┛ + + + +
    17. *    ┃┫┫ ┃┫┫
    18. *    ┗┻┛ ┗┻┛+ + + +
    19. */
    20. #include
    21. #include
    22. #include
    23. #include
    24. #include
    25. #include
    26. #include
    27. #include
    28. #include
    29. #define sc_int(x) scanf("%d", &x)
    30. #define sc_ll(x) scanf("%lld", &x)
    31. #define pr_ll(x) printf("%lld", x)
    32. #define pr_ll_n(x) printf("%lld\n", x)
    33. #define pr_int_n(x) printf("%d\n", x)
    34. #define ll long long
    35. using namespace std;
    36. const int N = 1000000 + 100;
    37. int n, m, h;
    38. ll s[N];
    39. ll cnt[N];
    40. mapint> q;
    41. int main()
    42. {
    43. int t;
    44. sc_int(t);
    45. while (t--)
    46. {
    47. cin >> n;
    48. int time = 0;
    49. for (int i = 1; i <= n; i++)
    50. {
    51. cin >> s[i];
    52. if (s[i] == 0)
    53. cnt[++time] = i;
    54. s[i] += s[i - 1];
    55. }
    56. cnt[++time] = n + 1;
    57. int res = 0;
    58. for (int i = 1; i < cnt[1]; i++)
    59. if (!s[i])
    60. res++;
    61. for (int i = 1; i < time; i++)
    62. {
    63. q.clear();
    64. int ma = 0;
    65. for (int j = cnt[i]; j < cnt[i + 1]; j++)
    66. {
    67. q[s[j]]++;
    68. ma = max(ma, q[s[j]]);
    69. }
    70. res += ma;
    71. }
    72. cout << res << endl;
    73. }
    74. return 0;
    75. }

  • 相关阅读:
    软件项目实施方案文档
    秒杀系统的设计与实现思路
    图像压缩原理-JPEG
    【原创】基于Jsp+Servlet的茶叶商城(在线商城毕业设计源代码)
    【Unity小功能开发实战教程】在UI画布上画网格线
    Vue(1)
    vue结合echarts时,浏览器报错Initialize failed: invalid dom
    【洛谷算法题】P5707-上学迟到【入门1顺序结构】
    定时器+按键控制LED流水灯模式+定时器时钟——“51单片机”
    c++11 多线程支持 (std::async)
  • 原文地址:https://blog.csdn.net/jikelk/article/details/128116146