Subsequence(POJ3061)

【英文题目】

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.

【简要翻译】

给出一个序列,求区间和大于或者等于S的最短区间长度,要求O(n)做法。

【分析】

法一:3重循环暴力枚举

法二:用前缀和去掉法一的1个循环,变成2重

法三:观察到序列非负即前缀和单调不减,可以枚举左端点再二分找到右端点,O(nlogn)的复杂度。

法四(我最先想到的方法,前3个都没想到):两个指针确定左右端点,则随着l指针单调递增,r指针一定不会递减。这是显然的:l指针右移之后当前区间和必然减小,那么就只能通过右移r指针补充,否则就与原来的[l,r]恰好满足条件矛盾(即[l,r-1]也满足)。

法四代码(一开始没看到题目说无解输出0,WA了好几发):

​
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100000+5;
int a[N];
int n,sum;
void work(){
	int ans=n,l=1,r=1,x=0;
	for (int i=1;i<=n;i++) x+=a[i];
	if (x<sum) {printf("0\n");return;} else x=a[1];
	while (l<=n){
	    if (x>=sum) ans=min(ans,r-l+1);
	    x-=a[l++];
	    while (x<sum && r<n) x+=a[++r];
	    if (r>=n && x<sum) break;
	}
	printf("%d\n",ans);
}
int main(){
  int T;
  scanf("%d",&T);
  while (T--){
	  scanf("%d%d",&n,&sum);
	  for (int i=1;i<=n;i++) scanf("%d",&a[i]);
  	  work();
  }
}
//缩进好像出锅了,将就着看吧。。。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值