POJ 3061—Subsequence(尺取法)

链接http://poj.org/problem?id=3061

题目
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.

输入
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.

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

样例输入

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

样例输出

2
3

题意
给定长度为n的整数数列以及整数S,求出总和不小于S的连续子串的长度的最小值。
如果解不存在,输出0。

思路
正常暴力会T掉,这里使用到的是尺取法

尺取法,顾名思义,像尺子一样取一段。

尺取法通常是对数组保存一对下标,即所选取的区间的左右端点,然后根据实际情况不断地推进区间左右端点以得出答案。

在这道题中,序列都是正数,如果一个区间其和大于等于S,那么不需要在向后推进右端点了,因为其和也肯定大于等于S但长度更长。
所以,当区间和小于S时右端点向右移动,和大于等于S时,左端点向右移动以进一步找到最短的区间
如果右端点移动到区间末尾其和还不大于等于S,结束区间的枚举。

直接上代码,「伊丽莎白」!
在这里插入图片描述
代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+100;
int t,n,s;
int a[maxn];
int main()
{
    ios::sync_with_stdio(false);  //加速流
    cin>>t;
    while(t--)
    {
        cin>>n>>s;
        for(int i=0; i<n; i++)
            cin>>a[i];
        int l=0,r=0,ans=n+1;   //l,r:左右端点  ans初始值设为n+1
        int sum=0;
        while(true)
        {
            while(r<n&&sum<s)
                sum+=a[r++];
            if(sum<s)         //如果所有数的和都小于s,直接跳出循环
                break;
            ans=min(ans,r-l); //此时r一定小于n(可以思考一下)
            sum-=a[l++];      //去掉最左端点,继续前进
        }
        if(ans==n+1)
            cout<<0<<endl;
        else
            cout<<ans<<endl;
    }
}

今天又是苦涩无味的一天(晚上跟一道BFS杠了2个小时,还没杠赢/(ㄒoㄒ)/~~)

在这里插入图片描述
这就是人生吧~

下次再见~
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值