POJ 3061 Subsequence(尺取法)

题目链接:?id=3061

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

尺取法:通常是指对数组保存一对下标(起点,终点),然后根据实际情况交替推进两个端点直到解决问题的方法,,这个操作很像尺蠼虫故得名。

思路:所以可以先初始化起点s,终点g,再一步一步推进,直到sum>S,然后记录此时的序列长度,再推进s,sum-=num[s],再记录长度,直到sum<S,再推进g,这样的方法,s和g最多各推进n次,所以复杂度是O(n)。

//556K79MS 尺取法#include<cstdio>#include<iostream>#include<algorithm>using namespace std;int a[100100];int main(){int cas,n,aim;scanf("%d",&cas);while(cas–){scanf("%d%d",&n,&aim);for(int i=1;i<=n;i++) scanf("%d",&a[i]);int s=0,g=0;int sum=0,ans=(1<<30);for(;;){while(sum<aim){g++;if(g>n) break;sum+=a[g];}if(sum<aim) break;ans=min(ans,g-s);sum-=a[++s];}if(ans>n) printf("0\n");else printf("%d\n",ans);}return 0;}当然,也可以历遍起点s,然后二分确定终点。复杂度O(NlogN)//948K79MS 二分#include<cstdio>#include<iostream>#include<algorithm>using namespace std;int a[100100],sum[100100];int main(){int cas;scanf("%d",&cas);while(cas–){int n,s,ans=(1<<30);scanf("%d%d",&n,&s);for(int i=1;i<=n;i++){scanf("%d",&a[i]);}for(int i=1;i<=n;i++){sum[i]=sum[i-1]+a[i];}if(sum[n]<s) {printf("0\n");continue;}for(int i=0;sum[i]+s<=sum[n];i++){int t=lower_bound(sum+i,sum+n+1,sum[i]+s)-(sum+i);ans=min(ans,t);}printf("%d\n",ans);}return 0;}

孑然一身,隐入苍茫自然,自有一种孤独的意味;旅行,

POJ 3061 Subsequence(尺取法)

相关文章:

你感兴趣的文章:

标签云: