POJ3061 Subsequence 尺取法

来源:互联网 发布:就业管理系统论文sql 编辑:程序博客网 时间:2024/04/28 04:17

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


题目大意:给定长度为n的整数数列a0,a1,...,an-1以及整数S,求出总和不小于S的子串的长度的最小值。如果不存在,那么长度为0。


分析:我们设以as开始的总和最初大于等于S时的连续子序列as,as+1,...,at-1,这时as+1,...,at-2<as,...,at-2<S,所以从as+1开始的总和不小于S的连续子序列如果是as+1,...,at'-1的话,则必然有t<=t',由此我们可得如下算法:

(1)以s=t=sum=0初始化;

(2)只要依然有sum<S,就不断将sum增加at,并将t++;

(3)如果(2)中无法满足sum>=S,则终止。否则更新ans=min(ans,t-s);

(4)将sum减去as,s+1然后回到(2)。


这种反复地推进区间的开头和末尾,来求取满足条件的最小的区间的方法被称作尺取法。


实现代码如下( 复杂度为O(n) ):

#include <cstdio>using namespace std;const int M=1e5+10;int a[M],n,S;int min(int x,int y){    return x<y?x:y;}void solve(){    int ans=n+1;    int s=0,t=0,sum=0;    while(true)    {        while(t<n&&sum<S)          sum+=a[t++];        if(sum<S) break;        ans=min(ans,t-s);        sum-=a[s++];    }    if(ans>n) ans=0; //解不存在    printf("%d\n",ans);}int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&S);        for(int i=0;i<n;i++)          scanf("%d",&a[i]);        solve();    }    return 0;}



0 0
原创粉丝点击