AYIT Online Judge 完美区间(尺取法)

题目链接http://acm.ayit.edu.cn/problem/68
在这里插入图片描述

尺取法
给定长度为n的数列整数a0,a1,a2…a(n-1)以及整数S。求总和不小于S的连续子序列的长度的最小值。如果不存在,输出0.
限制条件
10<n<1e5
0<ai<=1e4
S<1e8

输入:
n=10
S=15
5 1 3 5 10 7 4 9 2 8
输出:
2

第一种方法:前缀和+二分
时间复杂度O(nlogn)
规定:sum(i)=a0+a1+…+a(i-1)
子序列的起点s确定后,可以使用二分搜索快速地确定使序列和不小于S的结尾t的最小值
代码

int n,S;
int a[MAX_N];
void solve()
{
    for(int i=0; i<n; i++)/*0开始,下面的res=min(res,t-s)就不用进行-1的操作*/
        sum[i+1]=sum[i]+a[i];
    if(sum[n]<S)
        printf("0\n");
    return;
}
int res=n;
for(int s=0; sum[s]+S<=sum[n]; s++)
{
    int t=lower_bound(sum+s,sum+n,sum[s]+S)-sum;
    //以s为起点,一直到n,找到sum数组内,满足sum[i]>=sum[s]+S的i的最小值
    res=min(res,t-s);
}
printf("%d\n",res);

第二种方法:尺取法
设以a(s)为开始总和最初大于S时的连续子序列为a(s)+…+a(t-1),
如果从a(s+1)开始总和最初超过S的连续子序列如果是a(s+1)+…+a(t’-1)的话,必然有t<=t’.
t最多变化n次,所以时间复杂度O(n)
代码

void solve()
{
    int res=n+1;
    int s=0,t=0,sum=0;
    for(;;)
    {
        while(t<n&&sum<S)
            sum+=a[t++];
        if(sum<S)
            break;
        res=min(res,t-s);
        sum-=a[s++];
        //减去首位的数后,此时sum可能
        //sum>S,不执行while,往下更新最小值
        //sum<S,执行while,t对应的变化
    }
}
if(res>n)
    res=0;
printf("%d\n",res);

此题只是尺取法的运用
代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
int n,m;
int sum[N],a[N];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0; i<n; i++)
        scanf("%d",&a[i]);
    int s=0,t=0,sum=0,mi=inf,res=n,quary;
    for(;;)
    {
        while(t<n&&sum<m)
        {
            sum+=a[t++];
            int tab=abs(sum-m);
            if(tab<mi)
            {
                mi=tab;
                quary=t-s;
            }
            else if(tab==mi)
                quary=min(quary,t-s);
        }
        int tab=abs(sum-m);
        if(tab<mi)
        {
            mi=tab;
            quary=t-s;
        }
        else if(tab==mi)
            quary=min(quary,t-s);
        if(sum<m)
            break;
        sum-=a[s++];
    }
    printf("%d\n",quary);
    return 0;
}
发布了165 篇原创文章 · 获赞 6 · 访问量 5064

猜你喜欢

转载自blog.csdn.net/lylzsx20172018/article/details/103349152