clipboard.png
这道题可以利用二分来做,其实个人觉得动态规划也可以;
利用二分的前提条件就是该序列是一个不下降序列;
所以我们可以先构建一个sum数组,存放1-i的和值;
当然题目中要计算i-j子序列的值,其实这个可以利用sum数组来计算,该子序列的和就是sum[j]-sum[i];
所以我们就相当于对sum和二分序列寻找sum[i]+x,其中,x为题目前提给出的和值;

对于二分算法,使用大于x和大于等于x的两种都可以,示例给出的是大于x,然后通过判断j-1位是不是可以使得子序列和等于x;个人觉得麻烦,还是使用大于等于x较为简单;

其实这道题的关键还是怎么转化数组使得其能够用二分法进行解决;
还有一个问题,如果不仅仅包括0-n位,会出现第n位元素无法进行判断的情况,所以包括的序列一定要为1~n+1,这样就可以有效的使得随后一位进行计算,使得小于x的时候出现第n+1位无效位,从而根据位数是否无效来剔除这种意外之外的情况;

算法实现如下,使用的是大于等于x:

#include<iostream>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
const int maxn=100010;
int a[maxn],sum[maxn];
int n,m,ns=100000010;

int binarySearch(int l,int r,int x){
    while(l<r){
        int mid=(l+r)/2;
        if(sum[mid]>=x){
            r=mid;
        }else{
            l=mid+1;
        }
    }
    return l;
}

int main(){
    scanf("%d",&n);
    scanf("%d",&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    sum[0]=0;
    for(int i=1;i<=n;i++){
        sum[i]=sum[i-1]+a[i];
    }
    //此时sum递增;
    for(int i=1;i<=n;i++){
        int j=binarySearch(i,n+1,sum[i-1]+m);
        if(sum[j]-sum[i-1]==m){
            //如果存在和s相等的数;
            ns=m;
            break;
        }else if(j<=n&&sum[j]-sum[i-1]<ns){
            ns=sum[j]-sum[i-1];
        }
    }
    for(int i=1;i<=n;i++){
        int j=binarySearch(i,n+1,sum[i-1]+ns);
        if(sum[j]-sum[i-1]==ns){
            printf("%d-%d\n",i,j);
        }

    }
    system("pause");
    return 0;
}

宋霖轩
16 声望4 粉丝

克哈的霓虹都为我闪烁