代码源:677、弗拉德和糖果 II

333 阅读2分钟

本文已参与[新人创作礼]活动,一起开启掘金创作之路 logo.png

题目描述

这是4月13日代码源div2的每日一题。

弗拉德和糖果 II - 题目 - Daimayuan Online Judge

不久前,弗拉德过生日,他收到了一包糖果。有 n 种糖果,第 i 种糖果有 i 个(1≤i≤n)。

弗拉德决定每次只吃一个糖果。为了从吃东西中获得最大的乐趣,弗拉德不想连续吃两个相同类型的糖果。

帮助他弄清楚他是否可以在不连续吃两个相同的糖果的情况下吃掉所有的糖果。

简而言之,给定 n 个正整数 ai,aiai 表示有 ai 个 i,找到是否存在一种序列,使得所有的数都用上,且不存在 i 连续的情况

输入格式:

第一行,包含一个整数 n。 第二行,包含 n 个正整数。

输出格式:

输出一行,如果存在,输出YES,否则输出NO

样例输入

2
1 1

样例输出

YES

说明

只有两种情况:

1 2
2 1

无论先吃哪种糖果,都能吃完且不连续吃相同类型的糖果

数据限制

对于 100% 的数据,保证 1≤n≤5000000,1≤ai≤2^30

问题解析

这是一道思维题,我们只用看最大值与其他值的和的关系就行:

  • 当最大值大于其它值的和+1时,哪怕我们吃一口其它的糖,再吃一口最大数量的糖,最后也会剩下最大值的种类的糖,这样就必然要连着吃两个一样,所以要输出NO。

  • 当最大值等于其它值的和+1时,我们只要吃一口最大数量的糖,再吃一口其它数量的糖即可。这样就能正好吃完。输出YES。

  • 当最大值小于其它值的和+1时,我们可以先把其他数量的糖果内部消化到总和和最大值数量相等,这样就是第二种情况了。输出YES。

AC代码

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>

#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
const int MOD = 1e9 + 7, N = 1e6 + 10;

inline int read() {
    int x = 0; char ch = getchar();
    while (ch < '0' || ch > '9') ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x;
}

int main()
{
    int n;
    ll sum = 0, mx = 0,num;
    n = read();
    for (int i = 0; i < n; i++)
    {
        num = read();
        if (mx < num)
        {
            sum += mx;
            mx = num;
        }
        else sum += num;
    }
    if ((n == 1 && mx == 1) || mx <= sum + 1)
    {
        puts("YES");
    }
    else
    {
        puts("NO");
    }
    return 0;
}