语言:
子序列
描述 给出了一个N个正整数(10 <N <100 000)的序列,每个正整数小于或等于10000,并给出了一个正整数S(S <100 000 000)。编写程序以查找该序列的连续元素的子序列的最小长度,其总和大于或等于S。
输入项 第一行是测试用例的数量。对于每个测试用例,程序必须从第一行读取数字N和S,并以一个间隔将其隔开。序列号在测试用例的第二行中给出,以间隔分隔。输入将以文件结尾结束。
输出量 对于每种情况,程序都必须将结果打印在输出文件的单独一行上。如果没有答案,则打印0。
样本输入 2 10 15 5 1 3 5 10 7 4 9 2 8 5 11 1 2 3 4 5 样本输出 2 3 |
首先,如果一个区间其和大于等于S了,那么不需要在向后推进右端点了,因为其和也肯定大于等于S但长度更长,所以,当区间和小于S时右端点向右移动,和大于等于S时,左端点向右移动以进一步找到最短的区间,如果右端点移动到区间末尾其和还不大于等于S,结束区间的枚举。
#include<cstring> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int maxn=1e6+100; int a[maxn]; int n,s; int ans; void solve(){ ans=0x3f3f3f; int l=1,r=1,sum=0,res=0; while(r<=n){ while(sum<s&&r<=n){ sum+=a[r]; ++r; ++res; } while(sum>=s){ sum-=a[l]; l++; --res; } ans=min(ans,res+1); } } int main(){ int t; cin>>t; while(t--){ cin>>n>>s; int sum=0; int flag=0; for(int i=1;i<=n;i++){ cin>>a[i]; sum+=a[i]; } if(sum<s){ printf("0 "); } else{ solve(); printf("%d ",ans); } } }