标签:
1 /*
2 题意:求连续子序列的和不小于s的长度的最小值
3 尺取法:对数组保存一组下标(起点,终点),使用两端点得到答案
4 1. 记录前i项的总和,求[i, p)长度的最小值,用二分找到sum[p] - s[i] >= s的p
5 2. 除了O (nlogn)的方法,还可以在O (n)实现,[i, j)的区间求和,移动两端点,更新最小值,真的像尺取虫在爬:)
6 */
7 #include <cstdio>
8 #include <algorithm>
9 #include <cstring>
10 #include <cmath>
11 using namespace std;
12
13 typedef long long ll;
14 const int MAXN = 1e5 + 10;
15 const int INF = 0x3f3f3f3f;
16 int a[MAXN];
17 ll sum[MAXN];
18
19 int main(void) //POJ 3601 Subsequence
20 {
21 int t; scanf ("%d", &t);
22 while (t--)
23 {
24 memset (sum, 0, sizeof (sum));
25 int n, s;
26 scanf ("%d%d", &n, &s);
27 for (int i=1; i<=n; ++i) {scanf ("%d", &a[i]); sum[i] = sum[i-1] + a[i];}
28
29 if (sum[n] < s) {puts ("0"); continue;}
30
31 int ans = n;
32 for (int i=1; sum[i]+s<=sum[n]; ++i)
33 {
34 int p = lower_bound (sum+i, sum+1+n, sum[i] + s) - sum;
35 ans = min (ans, p - i);
36 }
37
38 printf ("%d\n", ans);
39 }
40
41 return 0;
42 }
43
44
45 /*
46 2
47 10 15
48 5 1 3 5 10 7 4 9 2 8
49 5 11
50 1 2 3 4 5
51 */
1 #include <cstdio>
2 #include <algorithm>
3 #include <cstring>
4 #include <cmath>
5 using namespace std;
6
7 typedef long long ll;
8 const int MAXN = 1e5 + 10;
9 const int INF = 0x3f3f3f3f;
10 int a[MAXN];
11
12 int main(void) //POJ 3601 Subsequence
13 {
14 int t; scanf ("%d", &t);
15 while (t--)
16 {
17 int n, s;
18 scanf ("%d%d", &n, &s);
19 for (int i=1; i<=n; ++i) scanf ("%d", &a[i]);
20
21 int ans = n + 1; int i = 1, j = 1; ll sum = 0;
22 while (1)
23 {
24 while (j <= n && sum < s) sum += a[j++];
25 if (sum < s) break;
26 ans = min (ans, j - i);
27 sum -= a[i++];
28 }
29
30 if (ans == n + 1) puts ("0");
31 else printf ("%d\n", ans);
32 }
33
34 return 0;
35 }
36
37
38 /*
39 2
40 10 15
41 5 1 3 5 10 7 4 9 2 8
42 5 11
43 1 2 3 4 5
44 */
标签:
原文地址:http://www.cnblogs.com/Running-Time/p/4550206.html