题目描述:
给你一个包含 N 个正整数的序列(10 < N < 100000),每个数都不超过 10000,还有一个正整数 S(S < 100000000)。请写个程序,找出序列中连续子序列的最短长度,使得这段子序列的和大于或等于 S。
输入格式:
第一行是测试用例的数量。每个测试用例的第一行包含两个数字 N 和 S,用空格分开。
第二行是序列中的 N 个数字,也用空格分开。输入以文件结束符结束。
输出格式:
每个测试用例输出一行结果,表示满足条件的最短子序列长度。如果找不到符合条件的子序列,就输出 0。
样例:
INPUT: | OUTPUT: |
---|---|
2 10 15 5 1 3 5 10 7 4 9 2 8 5 11 1 2 3 4 5 |
2 3 |
题解:
容易发现,直接暴力搜序列起点(i,j)时间复杂度为O(n^2),肯定会超时,分析如何降低复杂度至O(n)。观察可知,区间连续,采用双指针 l,r 枚举左右端点,求满足条件的区间最小值即可。
AC CODE:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+10;
int t,n,s,a[N],d[N];
int main(){cin>>t;while(t--){memset(d,0,sizeof(d));cin>>n>>s;for(int i=1;i<=n;i++){cin>>a[i];d[i]=d[i-1]+a[i];}if(d[n]<s) {cout<<0<<endl;continue;}int ans=N*100;for(int i=1,j=1;i<=j and i<=n and j<=n;i){if(d[j]-d[i-1]<s) j++;else ans=min(ans,j-i+1),i++;//cout<<ans<<" "<<i<<" "<<j<<endl;}cout<<ans<<endl;}return 0;
}