[CF]_[心得]_[870B]

话不多说先贴原题:

给定一个由n个整数组成的数组a1,a2,…,和整数k。您必须将数组拆分成k个非空的子段。然后,您将计算每个子段上的最小整数,并获取超过k个最小值的最大整数。你可以得到最大可能的整数是多少?
输入
第一行包含两个整数n和k(1≤k≤n≤10^5) - 数组a的大小和必须将数组拆分的子段数。
第二行包含n个整数a1,a2,…,an( - 10^9≤ai≤10^9)。

首先,分析题目,解的情况只有三种:

  1. k=1,这种情况最简单,由于只分一块,所以不难发现答案就是该数组的最小值。
  2. k>=3,此时原数组至少会被分成三块,所以只要将数组最大值单独分成一块,就可以使最终结果最大,所以此时答案是该数组的最大值。
  3. k=2,此时原数组被分为两块(下面称之为左(右)块),首先不妨设该数组的最小值处于数组中间某位置,此时从数组的一端(设为左端)开始尝试分块。若将端点值单独分为一块,则最大结果一定是该端点值,如图示:
    a1 | a2,…,min,…,an ( | 代表分割位置)。
    现在开始将分割位置逐位右移,对于伴随着分割位置的每一次右移,从右块进入左块的元素 X,若 (X>=a1) 则对于最终结果没有影响,若 (X<=a1)则该次右移“不合算”,因为此时的结果成了 X,而 X<=a1,使最终结果变小。所以当 K=2时,将端点元素单独分一组即为最优分割法,同时将上述步骤从右端开始,也可以得到相同的结论,所以,K=2时,答案就是数组的两个端点值中较大的。

还有一个问题,由于k,n的取值太大,数组开不下,只能采用边读入边处理的方法。

最后码程序:

#include<stdio.h>
int main(void)
{
    long long int n,k,i,ans,min,max,x;
    scanf("%lld%lld\n",&n,&k);
    max=-1000000009;
    min=1000000009;

    if (k==1)
        {
            for(i=1;i<=n;i++)
              {
                scanf("%lld",&x);
                if (x<min) min=x;   
              }
            ans=min;    
        }

    else if (k>=3)
            {
              for(i=1;i<=n;i++)
                 {
                    scanf("%lld",&x);
                    if (x>max) max=x;   
                 }
            ans=max;  
        }

    else
        {
          scanf("%lld",&max);
          for (i=2;i<=n;i++)  scanf("%lld",&x);
          if (max>x) ans=max;
          else ans=x;
        }
    printf("%lld",ans);             
    return 0;
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值