【和大于k最小长度连续子序列】 Subsequence

传送门

题意

给定长度为(N)的序列(a_{0},a_{1},dots,a_{n-1})以及整数(S),求出和不小于(S)的连续子序列的长度的最小值,如果解不存在输出(0)

数据范围

(10 < n < 10^{5})
(0< a_{i}leq 10^{4})
(S<10^{8})

题解

用两个指针,st和ed初始都指向序列的初始位置,然后只要和(< S)且未到达序列尾,ed就向后移动,当不能满足和(>=S)时退出,
满足和(< S)时每次st向前移动一次,取得满足条件的最小值即可,ed和st最多移动(2n)次,所以时间复杂度是(O(n))

Code

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<vector>
#include<list>
#include<queue>
#include<string>
#include<set>
#include<map>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define fi first
#define se second 
#define ll long long
#define pb push_back
typedef pair<long long,long long> pll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<long long> vll;
typedef double db;
const ll mod=1e9+7;
ll powmod(ll a,ll b,ll p){ll res=1;a%=p;while(b){if(b&1) res=res*a%p;a=a*a%p;b>>=1;}return res;}
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
const int N=1e5+10;
int n,s;
int seq[N];
int _;
int main(){
    for(scanf("%d",&_);_;_--){
        scanf("%d%d",&n,&s);
        rep(i,0,n) scanf("%d",&seq[i]);
        int st=0,ed=0,sum=0;
        int ans=1e7;
        for(;;){
            while(ed<n && sum<s)
                sum+=seq[ed++];
            if(sum<s) break;
            ans=min(ans,ed-st);
            sum-=seq[st++];
        }
        if(ans>n)
            ans=0;
        printf("%d
",ans);
    }
}
原文地址:https://www.cnblogs.com/hhyx/p/13205800.html