Subsequence 【poj-3061】【二分搜索】

Subsequence
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 18363   Accepted: 7852

Description

A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 100 000 000) are given. Write a program to find the minimal length of the subsequence of consecutive elements of the sequence, the sum of which is greater than or equal to S.

Input

The first line is the number of test cases. For each test case the program has to read the numbers N and S, separated by an interval, from the first line. The numbers of the sequence are given in the second line of the test case, separated by intervals. The input will finish with the end of file.

Output

For each the case the program has to print the result on separate line of the output file.if no answer, print 0.

Sample Input

2
10 15
5 1 3 5 10 7 4 9 2 8
5 11
1 2 3 4 5

Sample Output

2
3

题意:给出长度为n的整数序列,求出总和不小于s的连续子序列的长度的最小值,若不存在则输出0;

题解:本题有两种做法。第一种,利用二分搜索。第二种,利用尺取法。

二分(O(nlogn)):先用数组sum[ ]保存从开头累加的和,先判定是否存在解,然后遍历合适范围内数组sum[ ],对于每个sum[i]以此为起点运用lower_bound()函数找范围内的最小满足条件的t值,然后不断更新res值。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=100000+5;
int a[maxn];
int sum[maxn];
int main()
{
	int T;
	scanf("%d",&T);
	while(T--){
		int n,s;
		memset(sum,0,sizeof(sum));
		scanf("%d%d",&n,&s);
		for(int i=0;i<n;i++){
			scanf("%d",&a[i]);
		}
		for(int i=1;i<=n;i++){
			sum[i]=sum[i-1]+a[i-1];
		}
		if(sum[n]<s){
			printf("0\n");
			continue;
		}
		int res=n;
		for(int i=0;sum[i]+s<=sum[n];i++){
			int t=lower_bound(sum+i,sum+n,sum[i]+s)-sum;
			res=min(res,t-i);
		}
		printf("%d\n",res);
	}

	return 0;
}

尺取法(O(n)):看代码


#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=100000+5;
int a[maxn];
int main()
{
	int T;
	scanf("%d",&T);
	while(T--){
		int n,S;
		scanf("%d%d",&n,&S);
		for(int i=0;i<n;i++)
			scanf("%d",&a[i]);
		int res=n+1;
		int s=0,t=0,sum=0;
		while(1){
			while(t<n&&sum<S){//如果t已经更新到队尾或当前序列和已经大于等于S就跳出, 
				sum+=a[t++];
			}
			if(sum<S) break;//如果当前序列值已经无法满足需要就跳出 
			res=min(res,t-s);//更新res 
			sum-=a[s++];//剔除当前序列的第一个值,s++。即将当前序列的起点向后移一位。 
		}
		if(res>n) printf("0\n");
		else printf("%d\n",res);
		
	}
	
	return 0;
}


发布了79 篇原创文章 · 获赞 5 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/DNMTOOBA/article/details/79546977
今日推荐