尺取法

尺取法

Fri Oct 04 2024
zzcoe
3 分钟

尺取法(双指针法、two pointers)是一种常用的优化技巧,特别适用于解决序列的区间问题。它的操作简单,易于编程,是一种线性高效的算法。

尺取法的核心思想是维护一个区间(L,R),其中 L 为起点,R 为终点,该区间是序列内以 L 为起点的最短合法区间。关键在于 R 随着 L 的增大而增大。通过不断枚举 L,同时求解相应的 R,可以高效地解决问题。

具体的实现步骤是,不断移动 L 指针,同时更新 R 指针,直到 R 随着 L 的增大而增大。因为 R 随着 L 的增大而增大,所以总的时间复杂度为 O(n)。

通过维护两个指针,即左指针 l 和右指针 r。通过不断确定区间的左端点,让右指针 r 不断向右移动,直到满足条件停下,然后维护答案。这个过程重复进行,直到左指针 l 超过右指针 r 或满足其他特定情况(根据题目而定)。

尺取法的应用范围广泛,特别适用于需要寻找满足某种条件的连续子序列的问题。通过灵活运用尺取法,可以在保持算法简洁的同时,提高解题效率。

P8773 [蓝桥杯 2022 省 A] 选数异或 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

CPP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//悬殊疑惑
#include <iostream>
#include <cstring>
#include <queue>
#include <map>
using namespace std;
const int N =100005;
int n,m,x;
int a[N],f[N];
map<int,int> lst;
int main(){
	cin>>n>>m>>x;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		f[i]=max(f[i-1],lst[a[i]^x]);//以i为结尾,上一次满足题目的l在哪?既[f[i],i]区间满足条件
		lst[a[i]]=i;
	}
	for(int i=1;i<=m;i++){
		int l,r;
		cin>>l>>r;
		if(f[r]<l){
			cout<<"no"<<endl;
		}else{
			cout<<"yes"<<endl;
		}
	}
	return 0;
}