尺取法 POJ 3601 Subsequence

题目传送门

 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
", 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
", 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 */
O (n)
编译人生,运行世界!
原文地址:https://www.cnblogs.com/Running-Time/p/4550206.html