如题:http://poj.org/problem?id=3061
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 9164 | Accepted: 3661 |
Description
Input
Output
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
Source
题目大意:求给出数组某一段的和大于S,这一段的最小长度。
思路:第一种:输入的时候可以预处理求出sum[i]代表1-i个元素的和,然后用s从1-n遍历sum,每一次从s的位置二分搜索出第一个满足条件的区间,算出长度,如果比结果小就更新结果。O(nlogn)
第二种:第一种方法是固定一端(s),然后搜索满足的尾部t,我们可以头尾一起搜索。
初始化s=1,t=1,sum=0,如果sum<S,这是先动尾部,s不动,t++,一直到sum>=S,然后让头部++,继续缩小区间,如果不满足,再动尾部。复杂度O(n)。
第一种:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define min(a,b)(a<b?a:b)
int T,N,S;
int a[100005];
int sum[100005];
int main()
{
// freopen("C:\\1.txt","r",stdin);
cin>>T;
while(T--)
{
cin>>N>>S;
memset(sum,0,sizeof(sum));
int i;
for(i=1;i<=N;i++)
{
scanf("%d",&a[i]);
sum[i]+=sum[i-1]+a[i];
}
if(sum[N]<S)
{
printf("0\n");
continue;
}
int s,res=N;
for(s=1;sum[N]-sum[s]>=S;s++)
{
int t=lower_bound(sum+s,sum+N+1,sum[s]+S)-sum;
res=min(res,t-s);
}
printf("%d\n",res);
}
}
第二种:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define min(a,b)(a<b?a:b)
int T,N,S;
int a[100005];
int main()
{
// freopen("C:\\1.txt","r",stdin);
cin>>T;
while(T--)
{
cin>>N>>S;
int i;
int sum=0;
for(i=1;i<=N;i++)
scanf("%d",&a[i]);
int s=1,t=1;
int res=N;
while(1)
{
while(t<=N&&sum<S)
sum+=a[t++];
if(sum<S)
break;
res=min(res,t-s);
sum-=a[s++];
}
if(res==N)
res=0;
printf("%d\n",res);
}
}