尺取法(Sliding Window Technique),也称为滑动窗口算法,是一种常用于解决数组或字符串子区间问题的有效方法。其核心思想是通过维护一个窗口(子区间),在数组或字符串上滑动这个窗口,以找到满足特定条件的最优解。这种方法能够显著降低时间复杂度,尤其是在处理大数据集时。
以下是对尺取法的基本讲义,包括其原理、步骤和一些示例代码。
原理
尺取法的基本思想是利用两个指针(或称为“窗口的两端”)来维护一个当前考虑的子区间(窗口)。通过移动这两个指针,可以遍历所有可能的子区间,并在遍历过程中维护一些必要的状态信息(如窗口内的和、最大值、最小值等),从而找到满足条件的最优解。
步骤
- 初始化:
- 定义两个指针
left
和right
,分别表示窗口的左端和右端。 - 初始化一些必要的状态变量,如窗口内的和、最大值、最小值等。
- 定义两个指针
- 扩展窗口:
- 移动右指针
right
,扩展窗口,同时更新状态变量。 - 检查当前窗口是否满足条件。
- 移动右指针
- 收缩窗口:
- 如果窗口不满足条件,移动左指针
left
,缩小窗口,同时更新状态变量。 - 重复步骤 3 直到窗口满足条件或左指针超过右指针。
- 如果窗口不满足条件,移动左指针
- 记录结果:
- 在每次满足条件时,记录当前窗口的状态(如窗口大小、窗口内的和等),并在遍历结束后找到最优解。
- 继续遍历:
- 重复步骤 2-4,直到右指针遍历完整个数组或字符串。
例题
黑白奶牛(NHOI2016xjt4)
题目描述
有 N 只奶牛从左往右排成一行,编号是 1 至 N 。这 N 只奶牛当中,有一些奶牛是黑色的,其余的是白色的。
color[i] 表示第 i 只奶牛的颜色,如果 color[i]=0 则表示第 i 头奶牛是黑色的,如果 color[i]=1 则表示第 i 头奶牛是白色的。
六一奶牛儿童节快到了,农场主 Farmer John 要从这 N 头奶牛当中,挑选尽可能多的奶牛去参加晚会。
Farmer John 挑选奶牛的原则是:挑选编号是连续的一段奶牛,这一段奶牛的颜色必须全部是白色的。
Farmer John 有一个魔法棒,每用一次魔法棒就可以把一头黑色的奶牛变成一头白色的奶牛,魔法棒最多只能使用 K 次。
在上述条件下,最多可以有多少头奶牛去参加晚会呢?
输入格式
第一行,两个整数,N 和 K。
第二行,N 个整数,第 i 个整数就是 color[i] , color[i] 要么是 0,要么是 1。
数据规模
对于 50% 的数据,1 <= N <= 1000,K = 0 ,即不能使用魔法棒。
对于 100% 的数据,1 <= N <= 100000, 1 <= K <=N。
输出格式
一个整数,表示最多有多少头奶牛可以去参加晚会。
样例
输入数据 1
11 0
1 1 0 0 1 1 1 1 0 1 1
Copy
输出数据 1
4
Copy
输入数据 2
11 1
1 1 0 0 1 1 1 1 0 1 1
Copy
输出数据 2
7
Copy
样例解释
样例 1 :由于 K=0,所以不能使用魔法棒,所以挑选编号是 5 至 8 的奶牛去参加晚会。
样例 2 :由于 K=1,所以最多可以使用 1 次魔法棒,使用魔法棒把第 9 头奶牛变成白色奶牛,然后挑选编号是 5 至 11 的奶牛去参加晚会。
答案:
#include<iostream>
#include<fstream>
#include<algorithm>
using namespace std;
int n,l,k,hehe1[100000],a[100000],sum,ma;
int main()
{cin>>n>>k;for(int i=1;i<=n;i++){cin>>hehe1[i];a[i]=a[i-1];if(hehe1[i]==0) a[i]++;}for(int i=1;i<=n;i++){if(a[i]-a[l]<=k){sum++;if(i==n&&sum>ma){ma=sum;} }else{if(sum>ma){ma=sum;}l++;}}cout<<ma;return 0;
}