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

来源:互联网 发布:58中国网络经纪人登录 编辑:程序博客网 时间:2024/06/11 15:46

话不多说先贴原题:

给定一个由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; } 
原创粉丝点击