[传智杯]程序员节发橙子(C语言描述)

前言 座右铭:talk is easy,show me the code.
我们生活在幸福的时代,我们都站在巨人的肩膀上看世界

问题 2314: [传智杯]程序员节发橙子
时间限制: 2Sec 内存限制: 512MB 提交: 594 解决: 71

题目描述

每年的 1024 程序员节日,黑马程序员都会举办大型的庆祝活动。今年的程序员节也不例外,每个班级的同学都发了橙子。

班级里有 n 名同学从前到后排成一排,且已经得知了这些同学的成绩,其中第 i 名同学的成绩是
ai。班主任想根据同学们上个阶段的考试成绩来评定发橙子的数量。为了激励成绩优秀同学,发橙子时需要满足如下要求:

相邻同学中成绩好的同学的橙子必须更多。若相邻的同学成绩一样,则它们分到的数量必须平等。 每个同学至少分配一个橙子
由于预算有限,班主任希望在符合要求的情况下发出尽可能少的橙子。请问,至少需要准备多少橙子呢?

输入

第一行是一个不超过 10^6 正整数 n,表示学生数量。

接下来一行有 n 个不超过 10^9 的非负整数 ai,表示第 i 个同学的成绩。

输出

输出答案,也就是需要最少准备多少个橙子。

样例输入

5
3 4 5 4 3

样例输出

9

提示

样例解释:

每位同学拿到的橙子的数量分别是 1,2,3,2,1,所以至少需要准备 9 个

分析
数据的分析:
第一行输入不大于10^6 正整数 n,n使用整形即可
接下来一行有 n 个不超过 10^9 的非负整数 ai,表示第 i 个同学的成绩。
我们需要用一个数据sum来记录所以的人分得多少橘子,考虑一下最坏的情况,
10^9 *106=1015,显然sum不能为int型,因为int型数据在(-2.1 * 10^9~2.1 * 10^9)之间
而long long型 (-9.2 * 10^19~9.2 * 10^19),所以sum需要定义为long long型数据类型
思路就是:

第一个人的橘子数是1
如果局部成绩从第m个人到第n个人递增,分得橘子数目就是步长为1的递增

如果局部成绩从第m个人到第n个人递增相等,分得橘子树也相等

如果局部成绩从第m个人到第n个人递增递减,分得橘子数目就是从第n个人到第m个人f反向递增递
这时候需要分类讨论,因为说起来比较绕口,请读者仔细看我带代码仔细思考下列三种类型成绩是如何分配橘子的

例如 成绩 2 3 6 3 2 1
(这个成绩为6的学生反向递增是不需要奖励橘子的)

例如 成绩 2 3 4 3 2 1
(这个成绩为4的学生反向递增是需要奖励橘子的)

再例如 成绩 3 4 5 5 4 3 2 1
(这个两个成绩为5的学生都需要通过反向递增奖励橘子)

#include<stdio.h>
#include<malloc.h>
int main()
{
    int n,i;
    long long sum=0;
    scanf("%d",&n);
    int *a=(int *)malloc(n*sizeof(int ));
    int *b=(int *)malloc(n*sizeof(int ));
    for( i=0;i<n;++i)
    {
        scanf("%d",a+i);
        b[i]=0;
    }
    b[0]=1;
    for( i=1;i<n;++i)
     {
     //后面的比前面的大,多奖励一个橘子
        if(a[i]>a[i-1]) b[i]=b[i-1]+1; 
        //后一个跟前一个相等,分得一样多的橘子
        else if(a[i]==a[i-1]) b[i]=b[i-1]; 
        else if(a[i]<a[i-1])
        { //后一个小于前一个,这时候要麻烦一些
            b[i]=1;
            //从后往前面检查,让每一个分得的橘子合理
            for(int j=i-1;j>=0;--j) 
            {
                if(a[j]>a[j+1])
                {
                //反向递增,如果前面的大于后面,再奖赏前面一个橘子
                //你以为直接b[j]++吗?如果是这样,那你错完了
                //试想一下如果成绩依次
                // 5 6 3
                //直接b[j]++那岂不是 变成 依次分得  1 3 1橘子?
                //因为 反向递增 多奖励了第二个人一个橘子
                //因此我们需要设置条件
                if(b[j]<=b[j+1]) b[j]++; 
                }
                //3 4 5 5 4 3 2 1
                //如果成绩是这样的,
                //局部两个极大值相等成绩的学生橘子可能会不相等
                if(a[j]==a[j+1]) 
                {
                if(b[j]<b[j+1])b[j]=b[j+1];
                }    
                //反向不再递增,不再多奖励橘子
                else if(a[j]<a[j+1]) break; 
            }
        }
    }
    for(i=0;i<n;i++) 
    {
        sum+=b[i];
    }
    printf("%lld",sum);
    return 0;
}

由于水平有限,本博客难免有不足,恳请各位不吝赐教!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值