思路:二分查找
分析:
1 题目要求找到一个最短的子序列长度并且这个子序列的和大于等于给定的s
2 如果按照常规的做法枚举起点和终点的话肯定是会超时的。那么这里我们注意到给定的n个数都是正数,那么我们可以求出每一个数的前缀和
3 利用前缀和是递增的性质,那么我们在结合二分查找使得时间复杂度降到o(nlogn),那么这个是可以接受的。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int MAXN = 100010; int num[MAXN] , sum[MAXN]; int n , s; int search(int i){ int left , right , mid; left = 0 , right = i; while(left <= right){ int mid = (left+right)>>1; if(sum[i]-sum[mid] >= s) left = mid+1; else right = mid-1; } return i-right; } int solve(){ int ans = MAXN; for(int i = 1 ; i <= n ; i++){ if(sum[i] >= s) ans = min(ans , search(i)); } return ans == MAXN ? 0 : ans; } int main(){ while(scanf("%d%d" , &n , &s) != EOF){ memset(sum , 0 , sizeof(sum)); for(int i = 1 ; i <= n ; i++){ scanf("%d" , &num[i]); sum[i] = num[i] + sum[i-1]; } printf("%d\n" , solve()); } return 0; }