目录
前言
双指针尺取法是个可以降低时间复杂度的好东西,和二分类似
一、双指针尺取法是什么?
利用变量指针i,j首末缩或头尾推的一种算法
二、例题
1.P1102 A-B 数对
首先 ,这题是道二分和尺取法都能做的题
二分就不叙述了
其次,尺取法这题是先排序,头尾推
相同的加1
不相同的分两部分
一部分用r1
另一部分用r2
r1的循环条件为a[r1] - a[l] <= c
r2的循环条件为
a[r2] - a[l] < c
最后ans+=r1-r2
输出ans就行了
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 10;
int n , c;
int a[N];
int main ()
{
cin >> n >> c;
for(int i = 1 ; i <= n ; i ++) cin >> a[i];
sort(a + 1 , a + 1 + n);
int l = 1, r1 = 1 , r2 = 1;
ll ans = 0;
for(l = 1 ; l <= n ; l ++) {
while(r1 <= n && a[r1] - a[l] <= c) r1 ++;
while(r2 <= n && a[r2] - a[l] < c ) r2 ++;
if(a[r2] - a[l] == c && a[r1 - 1] - a[l] == c && r1 - 1 >= 1)
ans += r1 - r2;
}
cout << ans;
return 0;
}
2.P1638 逛画展
代码如下(示例):
#include<bits/stdc++.h>
using namespace std;
int a[2009],num=0,b[1000009],R=0,L=1,N,M,t,i=0,ansL,ansR;
int main(){
scanf("%d %d",&N,&M);
for(i=1;i<=N;i++) scanf("%d",b+i);
i=1;
while(num!=M){
if(a[b[i]]==0)num++;
a[b[i]]++;
R++;
i++;
}
while(a[b[L]]>1) a[b[L++]]--;
ansL=L;
ansR=R;
while(i<=N){
a[b[i]]++;
R++;
i++;
while(a[b[L]]>1) a[b[L++]]--;
if(ansR-ansL>R-L){
ansR=R;
ansL=L;
}
}
printf("%d %d",ansL,ansR);
return 0;
}
总结
尺取法需要大量习题来巩固