#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
int a[100010];
int main()
{
long long n,s,t,sum,ans;
int left,right,i,j;
// freopen("in.txt","r",stdin);
cin>>t;
for (j=1;j<=t;j++)
{
cin>>n>>s;
memset(a,0,sizeof(a));
for (i=1;i<=n;i++) cin>>a[i];
ans=n+1;
sum=0;
left=1;
for (right=1;right<=n;)
{
while (sum<s&&right<=n) sum+=a[right++];
right--;
while (sum>=s)
{
if (right-left+1<ans) ans=right-left+1;
sum-=a[left++];
}
right++;
}
if (ans==n+1) cout<<'0';else cout<<ans;
cout<<endl;
}
//cout << "Hello world!" << endl;
return 0;
}
求一个子序列的长度,这个子序列之和必须大于指定的一个值limit,且必须长度最小,求出这个序列的最小长度。
开头和末尾
,来求满足条件的最小区间的方法称为尺取法。
主要思想为:当a1, a2 , a3 满足和>=S,得到一个区间长度3,那么去掉开头a1, 剩下 a2,a3,判断是否满足>=S,如果满足,那么区间长度更新,如果不满足,那么尾部向后拓展,判断a2,a3,a4是否满足条件。重复这样的操作。
当一个区间满足条件时,那么去掉区间开头第一个数,得到新区间,判断新区间是否满足条件,如果不
满足条件,那么区间末尾向后扩展,直到满足条件为之,这样就得到了许多满足条件的区间,再根据题
意要求什么,就可以在这些区间中进行选择,比如区间最长,区间最短什么的。这样跑一遍下来,时间
复杂度为O(n)