POJ 3061 · Subsequence【子序列】【尺取法】

【题意】

给定长度为n的数列整数 a0,a1,,an1 以及整数S。求出总和不小于S的连续子序列的长度的最小值。如果解不存在,则输出0。
限制条件:
10<n<105
0<ai104
S<108

【提炼】

略。

【分析】

之前讲过二分怎么想,右戳链接

现在讲讲怎么用 尺取法 来做:
要求: as++at1S
这时, as+1++at2<as++at2<S
也就是说,从 as+1 开始总和最初超过S的连续子序列如果是 as+1++at1 ,那么必然有 tt
利用上述性质便可
反复地推进区间的开头和结尾,来求取满足条件的最小区间
这种方法叫尺取法。

【时间复杂度】

由于t最多变化n次,所以时间复杂度为

O(n)

【代码】

/*
    coder: Tangent Chang
    data:  2017/5/9
    I just like you.
*/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <algorithm>

using namespace std;

const int maxn = 100005;

int d[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", &d[i]);
        }
        int sum = 0, s = 0, t = 0, res = n + 1;
        while (1) {
            while (t < n && sum < S) {
                sum += d[t++];
            }
            if (sum < S) break;
            res = res < t - s ? res : t - s;
            sum -= d[s++];
        }
        if (res > n) {
            res = 0;
        }
        printf("%d\n", res);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值