尺取法 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\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 */

O (n)

时间: 2024-10-11 12:36:46

尺取法 POJ 3601 Subsequence的相关文章

从具体题目来谈尺取法 POJ 3061 Subsequence

题目链接:http://poj.org/problem?id=3061 先说说最朴素的算法,那就是for嵌套了,复杂度是O(n^3)太慢,想都不用想一定会超时.接下来有的人可能会想到二分搜索的思想,将时间复杂度优化成O(n*logn),我试了一下,可以AC. 但是这都不是今天要说的重点,今天要说的是一个ACM比赛中常用的技巧方法——尺取法.这是一种可以直接将时间复杂度优化到O(n)的算法. 我们先来介绍一下尺取法.尺取法,顾名思义,像尺子一样,一块一块的截取.是不是解释的有点让人纳闷-..没关系

尺取法 POJ 3320 Jessica&#39;s Reading Problem

题目传送门 1 /* 2 尺取法:先求出不同知识点的总个数tot,然后以获得知识点的个数作为界限, 更新最小值 3 */ 4 #include <cstdio> 5 #include <cmath> 6 #include <cstring> 7 #include <algorithm> 8 #include <set> 9 #include <map> 10 using namespace std; 11 12 const int M

POJ 3061 Subsequence(尺取法)

传送门 Subsequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11284 Accepted: 4694 Description 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) ar

POJ 3061 Subsequence(尺取法)

题目链接:http://poj.org/problem?id=3061 题意:给定长度为n的数列整数,以及整数S,求出总和不少于S的连续子序列的长度的最小值.如果解不存在,则输出0. 尺取法:通常是指对数组保存一对下标(起点,终点),然后根据实际情况交替推进两个端点直到解决问题的方法,这个操作很像尺蠼虫故得名. 思路:所以可以先初始化起点s,终点g,再一步一步推进,直到sum>S,然后记录此时的序列长度,再推进s,sum-=num[s],再记录长度,直到sum<S,再推进g,这样的方法,s和g

[ACM] POJ 3061 Subsequence (尺取法)

Subsequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8403   Accepted: 3264 Description 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

POJ 3061 Subsequence (二分||尺取法)

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 sequen

POJ 3061 Subsequence ( 二分 || 尺取法 )

题意 : 找出给定序列长度最小的子序列,子序列的和要求满足大于或者等于 S,如果存在则输出最小长度.否则输出 0(序列的元素都是大于 0 小于10000) 分析 : 有关子序列和的问题,都可以考虑采用先构造前缀和的方式来进行接下来的操作 ( 任意子序列的和都能由某两个前缀和的差表示 ). 二分做法 ==> 我们枚举起点,对于每一个起点 St 二分查找看看 St 后面有没有前缀和是大于或者等于 [ St的前缀和 ] + S 的,如果有说明从当前起点开始有一个终点使得起终之和是大于或者等于 S 的,

poj3061 Subsequence ,尺取法

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 sequen

poj 3320 Jessica&#39;s Reading Problem(尺取法+map/hash)

题目:http://poj.org/problem?id=3320 题意:给定N个元素的数组,找出最短的一段区间使得区间里面的元素种类等于整个数组的元素种类. 分析:暴力枚举区间的起点x,然后找到最小的y,使得区间[x,y]满足条件,x向有移位后变成x',现在的y'肯定不至于在y的左边.存状态的话map和hash都可以. map代码: #include <iostream> #include <set> #include <map> #include <cstdi