UVALive 2678 利用序列的前缀来减少时间复杂度

题意很简单,在一串正整数序列中找一个连续的子序列使该序列和大于等于一个已知量S,但要求序列长度最短,通常喜欢暴力枚举

这个题目跟大白书之前的一个题目很像,在数列A中 求 Ai-Aj最大 并且 i<J;这个题目巧妙一点,就直接只枚举j,然后在枚举j的过程中不断更新j前面的最大值即为Ai,即可只用O(n)的复杂度

同样,本题也是,先预处理下,把每个数的前缀和B求出来,这样求某一子序列 只要知道起终点,直接用B[J]-B[i]即可,只是枚举子序列的终点j,初始起点设置为i=0,如果满足B[j]-B[i]>=S,则不断增加i,否则,就增加j。这样只是枚举了一下终点,而找到起点几乎是常数时间。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int num[100010];
int B[100010];
int main()
{
    int n,s;
    while (scanf("%d%d",&n,&s)!=EOF)
    {
        for (int i=0;i<n;i++)
        {
            scanf("%d",&num[i]);
        }
        B[0]=0;
        for (int i=1;i<=n;i++)
        {
            B[i]=B[i-1]+num[i-1];
        }
        int ans=n+1;
        int i=0;
        for (int j=1;j<=n;j++)
        {
            int temp=B[j]-B[i];
            if (temp<s) continue;
            while (B[j]-B[i]>=s) i++;
            ans=min(ans,j-i+1);
        }
        if (ans==n+1) ans=0;
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/kkrisen/p/3553970.html