Codeforces Round #668 (Div. 2) B

Codeforces Round #668 (Div. 2) B

/ 1评 / 1962次 / 0

B. Array Cancellation

Description

给定一个有n个整数的数组a

每次都可以选择任意两个不同的ij,进行如下操作

操作A:a[i];a[j]++;

操作B:a[i]++;a[j];

其中操作A可以无限免费执行,而操作B每次需要消耗一个金币。现请求出最少需要多少个金币才能使数组a中各项归零

题目保证ni=1ai=0

Input

第一行一个整数t代表组数

之后每一组由两行构成,第一行为整数n表示该组有n个整数,第二行为n个整数

Output

一个整数代表最少需要的金币个数

Analysis

太久没做题了,遇到这个题目一开始还有些没有头绪

我个人认为比较容易想到的做法是这样

从前向后考虑数列第一项,若第一项小于0则必然这个数对答案的贡献就是其相反数(因为这个数只能通过操作B来归零),若其大于0则其就可以允许之后的负数在上升的时候可以使用其归零所留下了富余值

定义两个变量记为lefans分别代表富余值与答案

我们通过一个样例来具体说明,如

  1. 4
  2. -3 5 -3 1
4
-3 5 -3 1

a1归零需要对答案产生3的贡献 lef=0,ans=3

a2归零可以允许之后的负数上升5 lef=5,ans=3

a3归零可以利用lef故不对答案产生贡献 lef=2,ans=3

a4归零不对答案产生贡献

故答案为3

更加复杂的样例如

  1. 7
  2. -5 7 -6 -4 17 -13 4
7
-5 7 -6 -4 17 -13 4

a1归零需要对答案产生5的贡献 lef=0,ans=5

a2归零可以允许之后的负数上升7 lef=7,ans=5

a3归零可以利用lef故不对答案产生贡献 lef=1,ans=5

a4归零对答案产生3的贡献 lef=0,ans=8

a5归零可以允许之后的负数上升17 lef=17,ans=8

a6归零可以利用lef故不对答案产生贡献 lef=4,ans=8

a7归零不对答案产生贡献

故答案为8

Accepted Code

  1. /*
  2. * @Author : Gehrychiang
  3. * @LastEditTime : 2020-09-07 10:11:40
  4. * @Website : www.yilantingfeng.site
  5. * @E-mail : gehrychiang@aliyun.com
  6. * @ProbTitle : Array Cancellation
  7. */
  8. #include <bits/stdc++.h>
  9. using namespace std;
  10. typedef long long ll;
  11. template <class T>
  12. void _R(T &x) { cin >> x; }
  13. void _R(int &x) { scanf("%d", &x); }
  14. void _R(long long &x) { scanf("%lld", &x); }
  15. void _R(double &x) { scanf("%lf", &x); }
  16. void _R(char &x) { scanf(" %c", &x); }
  17. void _R(char *x) { scanf("%s", x); }
  18. template <class T>
  19. void _W(const T &x) { cout << x; }
  20. void _W(const int &x) { printf("%d", x); }
  21. void _W(const long long &x) { printf("%lld", x); }
  22. void _W(const double &x) { printf("%.16f", x); }
  23. void _W(const char &x) { putchar(x); }
  24. void _W(const char *x) { printf("%s", x); }
  25. ll a[100005];
  26. int main()
  27. {
  28. int t;
  29. _R(t);
  30. while (t--)
  31. {
  32. int n;
  33. _R(n);
  34. for (int i = 0; i < n; i++)
  35. {
  36. _R(a[i]);
  37. }
  38. ll lef = 0;
  39. ll ans = 0;
  40. for (int i = 0; i < n; i++)
  41. {
  42. if (a[i] < 0)
  43. {
  44. a[i] += lef;
  45. lef = 0;
  46. }
  47. if (a[i] < 0)
  48. {
  49. ans += -a[i];
  50. }
  51. else
  52. {
  53. lef += a[i];
  54. }
  55. }
  56. _W(ans);
  57. _W("\n");
  58. }
  59. return 0;
  60. }
/*
 * @Author       : Gehrychiang
 * @LastEditTime : 2020-09-07 10:11:40
 * @Website      : www.yilantingfeng.site
 * @E-mail       : gehrychiang@aliyun.com
 * @ProbTitle    : Array Cancellation
 */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template <class T>
void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(long long &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
template <class T>
void _W(const T &x) { cout << x; }
void _W(const int &x) { printf("%d", x); }
void _W(const long long &x) { printf("%lld", x); }
void _W(const double &x) { printf("%.16f", x); }
void _W(const char &x) { putchar(x); }
void _W(const char *x) { printf("%s", x); }
ll a[100005];
int main()
{
    int t;
    _R(t);
    while (t--)
    {
        int n;
        _R(n);
        for (int i = 0; i < n; i++)
        {
            _R(a[i]);
        }
        ll lef = 0;
        ll ans = 0;
        for (int i = 0; i < n; i++)
        {
            if (a[i] < 0)
            {
                a[i] += lef;
                lef = 0;
            }
            if (a[i] < 0)
            {
                ans += -a[i];
            }
            else
            {
                lef += a[i];
            }
        }
        _W(ans);
        _W("\n");
    }

    return 0;
}

《“Codeforces Round #668 (Div. 2) B”》 有 1 条评论

  1. rantrism说道:

    您好~我是腾讯云+社区的运营,关注了您分享的技术文章,觉得内容很棒,我们诚挚邀请您加入腾讯云自媒体分享计划。完整福利和申请地址请见:https://cloud.tencent.com/developer/support-plan
    作者申请此计划后将作者的文章进行搬迁同步到社区的专栏下,你只需要简单填写一下表单申请即可,我们会给作者提供包括流量、云服务器等,另外还有些周边礼物。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

你好 No.98438