POJ - 3061 Subsequence
给出了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
尺取:
犹如使用尺子一样,左右端点一同往右移动。
左端:i,右端 j
首先取得一个能满足15的最小序列,依次将l右移,如果移动后仍然符合情况,j不动,否则j右移。
过程模拟:
5 1 3 5 10 7 4 9 2 8
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<vector>
#include<string>
#define M 100005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int T,N;
ll S;
int num[M];
int main(){
scanf("%d",&T);
while(T--){
scanf("%d %lld",&N,&S);
for(int i=0; i<N; i++)
scanf("%d",&num[i]);
int r = 0,l = 0;
int ans = INF;
ll sum = 0;
while(1){
while(r<N && sum<S) //右端移动找到满足的段
sum += num[r++];
if(sum<S) //全部相加都不够,直接跳出
break;
ans = min(ans,r-l); //左端点向右移
sum -= num[l++];
}
if(ans>N) ans = 0;
printf("%d\n",ans);
}
return 0;
}