poj3061 Subsequence
Subsequence
POJ - 3061题目大意:
给定长度为n的整数数列,以及整数S。求出总和不小于S的连续子序列的长度的最小值。若解不存在,则输出0.
Sample Input
2 10 15 5 1 3 5 10 7 4 9 2 8 5 11 1 2 3 4 5
Sample Output
2 3
/* 求出前缀和,然后枚举区间起点 区间起点固定下来了之后,终点位置二分查找 不要忘了输出0的情况 */ #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; #define maxn 100010 int t,n,a[maxn],sum[maxn],s; int main(){ //freopen("Cola.txt","r",stdin); scanf("%d",&t); while(t--){ memset(a,0,sizeof(a)); memset(sum,0,sizeof(sum)); scanf("%d%d",&n,&s); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); sum[i]=sum[i-1]+a[i]; } if(sum[n]<s){printf("0\n");continue;} int ans=n; for(int i=1;i<=n;i++){//枚举起点 int l=i,r=n;//二分中点 while(l<=r){ int mid=(l+r)>>1; int now=sum[mid]-sum[i-1]; if(now>=s)r=mid-1,ans=min(ans,mid-i+1); else l=mid+1; } } printf("%d\n",ans); } }
/* 尺取法: 1.初始化s,t,sum 2.只要依然有sum<m,就不断将sum加a[t],并将t加1 3.如果(2)中无法满足sum>=m则终止。否则更新ans 4.将sum减去a[s],s加1然后回到2 像区间右移 */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define maxn 100010 int T,n,t,a[maxn],s,m,sum; int main(){ scanf("%d",&T); while(T--){ s=1;t=0; sum=0; bool flag=0; scanf("%d%d",&n,&m); int ans=n; for(int i=1;i<=n;i++)scanf("%d",&a[i]); while(1){ while(t<n&&sum<m) sum+=a[++t]; if(sum<m)break; ans=min(ans,t-s+1);flag=1; sum-=a[s];s++; } if(flag==0){printf("0\n");continue;} else printf("%d\n",ans); } return 0; }