POJ 3601 Subsequence

题目描述:

给你一个包含 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;
}
posted @ 2025-09-11 15:45  kagmy_yzssy  阅读(24)  评论(0)    收藏  举报