版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎添加友链。 https://blog.csdn.net/qq_42835910/article/details/89817550
A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 100 000 000) are given. Write a program to find the minimal length of the subsequence of consecutive elements of the sequence, the sum of which is greater than or equal to S.
分析:计算前缀和sum[i].那么问题就是对于j为终点,i为起点,枚举j,求解sum[j] - sum[i] >= s(即sum[i] <= sum[j] - s)成立时 i 的最大值(i越大,序列越短),ans = min{ j-i+1}。
方法一:二分,时间复杂度O(nlogn).
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 100000 + 5;
int nums[N], sums[N];
int main(int argc, char** argv) {
int n, s;
while( ~scanf("%d%d",&n,&s)){
for(int i = 1; i <= n; i++){
scanf("%d",&nums[i]);
sums[i] = sums[i-1] + nums[i];
}
int ans = n+1;
for(int j = n; j >= 1; j--){
int y = sums[j] - s;
if(y < 0) break; //前j个数的和小于s,后面不可能继续;
int i = lower_bound(sums ,sums+j, y) - sums;
if(i > 0) ans = min(j-i+1,ans);
}
printf("%d\n",ans == n+1 ? 0 : ans);
}
return 0;
}
方法二:由于j是递增的,那么sum[j] - s 的位置也是递增的,那么sum[i] <= sum[j] - s 的右边也是递增的,显然满足条件的
i也是递增的.时间复杂度O(n)
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 100000 + 5;
int nums[N], sums[N];
int main(int argc, char** argv) {
int n, s;
while( ~scanf("%d%d",&n,&s)){
for(int i = 1; i <= n; i++){
scanf("%d",&nums[i]);
sums[i] = sums[i-1] + nums[i];
}
int ans = n+1, i = 1;
for(int j = 1; j <= n; j++){
int y = sums[j] - s;
if(y < 0) continue; //没有满足条件的i,换下一个j
while(sums[i] <= y) i++; //求满足b[i-1] <= b[j] - s 的最大i
ans = min(j-i+1,ans);
}
printf("%d\n",ans == n+1 ? 0 : ans);
}
return 0;
}