题目链接:http://poj.org/problem?id=3061
题意:给n个正整数和一个数S,求出总和不小于S的连续子序列的长度的最小值,如果无解输出0;
我们可以用sum[i]表示前i项的和;然后二分枚举找答案即可时间复杂度为O(n*logn)的;
#include<iostream> #include<algorithm> #include<string.h> #include<stdio.h> #include<math.h> using namespace std; #define N 120000 #define PI 4*atan(1.0) #define mod 110119 #define met(a, b) memset(a, b, sizeof(a)) typedef long long LL; int a[N], n, s, sum[N]; int Judge(int len) { for(int i=1; i+len-1<=n; i++) { if(sum[i+len-1]-sum[i-1]>=s) return 1; } return 0; } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d %d", &n, &s); for(int i=1; i<=n; i++) { scanf("%d", &a[i]); sum[i] = sum[i-1] + a[i]; } int L = 1, R = n, Min = 0; while(L <= R) { int Mid = (L+R)/2; if(Judge(Mid)) { Min = Mid; R = Mid-1; } else L = Mid+1; } printf("%d\n", Min); } return 0; }
还可以用尺取法,就是用两个指针控制一下头和尾,然后移动即可;时间复杂度是O(n)的;
#include<iostream> #include<algorithm> #include<string.h> #include<stdio.h> #include<math.h> using namespace std; #define N 120000 #define PI 4*atan(1.0) #define mod 110119 #define met(a, b) memset(a, b, sizeof(a)) typedef long long LL; int a[N], n, s; int main() { int T; scanf("%d", &T); while(T--) { scanf("%d %d", &n, &s); for(int i=1; i<=n; i++) scanf("%d", &a[i]); int L = 1, R = 1, ans = n+1, sum = 0; while(1) { while(R<=n && sum<s) sum += a[R++]; if(sum < s) break; ans = min(ans, R-L); sum -= a[L++]; } if(ans == n+1)ans = 0; printf("%d\n", ans); } return 0; }
时间: 2024-10-05 08:31:56