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.
Sample Input
2
10 15
5 1 3 5 10 7 4 9 2 8
5 11
1 2 3 4 5
Sample Output
2
3
翻译:
给出了N个正整数(10<N<100000)的序列,每个正整数小于或等于10000,一个正整数S(S<109)。写一个程序求序列中连续元素的子序列的最小长度,其和大于或等于S。
尺取法的分析:尺取法在cf用“two pointers"来表示,即它使用两个指针来枚举所需子序列,他比一般用for循环的枚举更为高效和便捷,他的效率体现在,我们一旦发现子区间符合题意后,接下来的操作就是有关于如何推进区间端点,换句话说,凡是用尺取法的问题,就是与区间端点取舍的相关问题
整个尺取法基本上分为四步
第一步:初始化左右端点
第二步:不断扩大右端点,直到首先满足题意
第三步:满足题意后,终止,更新结果
第四步:扩大左端点,收缩区间,回到第二步
这块借用了大神的图,侵删

分析:首先我们将两个指针都定为左端点,然后向右扩大右端点,知道10被染色,这个区间就满足题意了,总和为24,然后收缩左端点直到只有10,在这个过程中 , 我们贪心求出最小长度就是2,之后右指针向右扩张,在收缩,每次贪心求出长度一一比较即可
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e5 + 100;
int a[N];
int main()
{
int t = 0;
cin >> t;
while (t --)
{
memset (a , 0 ,sizeof a);
int n , s;
int l = 0 ,r = 0;
int ans = 0x3f3f3f;
cin >> n >> s;
for (int i=1; i<=n; i ++) cin >> a[i];
int sum = 0;
while (r <= n && l <= r)
{
if (sum >= s) //这里用到了两次if,便于排查
{
ans = min (ans , r - l + 1);
sum -= a[l];
l ++ ;
}
if (sum < s)
{
r ++ ;
sum += a[r];
}
}
if (ans == 0x3f3f3f) cout << 0 << endl; //我没有粘贴完题,如果没有找到符合题意的子序列,就输出0
else cout << ans << endl;
}
return 0;
}
本文介绍了一种利用尺取法解决特定序列问题的方法,通过给定的正整数序列及目标值S,寻找序列中连续元素子序列的最小长度,其和大于或等于S。
&spm=1001.2101.3001.5002&articleId=114228872&d=1&t=3&u=5955fc5acc864084879c437828673425)

被折叠的 条评论
为什么被折叠?



