贪心
例题
2)
双指针
双指针通常用于在数组或字符串中进行快速查找、匹配、排序或移动操作。
双指针并非真的使用指针实现,一般用两个变量来表示下标(在后面都用指针来表示)。
常见的指针模型:1)对撞指针 2)快慢指针
对撞指针
指的是两个指针left, right(简写 l , r),分别指向序列的第一个元素和最后一个元素。
然后在满足一定条件后不断递减或递增。
直到左右指针相撞( l==r)。
例题:
快慢指针
指的是两个指针从同一侧开始遍历序列,且移动的歩长一个快一个慢。
步骤:
使用两个指针 l,r ,l 指向序列的第一个元素,r一般指向序列的第零个元素,都像右边移动,直至l==n且r==n,或两指针相交跳出循环。
例题:
二分
整数二分
就是在一个已有的有序数组上进行二分查找,一般为找出某个值的位置,或者是找出分界点。数组大小一般在1e6以内。
//整数二分模板
int l = 0, r = 1e9;
while (l + 1 != r)
{
int mid = (l + r) / 2;
if (a[mid] >= x) r = mid;
else l = mid;
}
cout << r << '\n';
例题
浮点二分
不在是在有序数组上二分查找,而是在某个实数范围内进行查找。实数域本身也是单调的。
区别:使用的变量类型,退出的判断条件。(不太重要)
//浮点二分模板
double l = 0, r = 1e9, esp = 1e-6;
//这样的判断条件可保证l r最终可以收敛到分界点
while (r - 1 >= esp) // esp是一个极小值,设置为1e-6较为合适
{
double mid = (l + r) / 2;
//f(x)单调增,f(x)>=0,说明mid偏大。
if (f(mid) >= 0) r = mid;
else l = mid;
}
cout << r << '\n'; //返回l,r,差别不大
二分答案
二分法最常见最重要的题型。
模型:二分框架+check函数
我们会将答案进行二分 ,然后枚举可能解后判断是否可以更优或是否合法,不断逼近最优解。
特征:已知某个答案,容易判断是否合法或更优。
//二分答案
bool check(int mid)
{
bool res = true;
return res;//判断中点的合法性
}
int main()
{
int l = 0, r = 1e9;
while (l + 1 != r)
{
int mid = (l + r) / 2;
if (check(mid)) l = mid;
else r = mid;
}
cout << l << '\n';
return 0;
}
例题:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=5e4+9;
int a[N],L,n,m;
int check(int mid)
{
int res=0,lst=0;
for(int i=1;i<=n;++i)
{
if(a[i]-a[lst]<mid)//lst 上一个数
{
res++;
continue;
}
lst =i;
}
if(L-a[lst]<mid) return m +1;//表示不允许
return res;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>> L>>n>>m; //距离,岩石数,至多移走的岩石数
for(int i=1;i<=n;++i) cin>> a[i];
ll l=0,r=1e9+5;
while(l+1!=r)
{
ll mid=(l+r)/2;
if(check(mid)<=m) l=mid;
else r=mid;
}
cout << l << '\n';
return 0;
}
例题:
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+9;
int x[N];
int n,m;
int check(int mid)
{
int res=0;
for(int i=1,lst =0;i<=n;++i)
{
if(lst && x[i]-x[lst]<mid) continue;
res++,lst=i;
}
return res;
}
int main()
{
cin>> n >>m;
for(int i=1;i<=n;++i) cin>> x[i];
sort(x+1,x+1+n);
int l=0,r=1e9+5;
while(l+1!=r)
{
int mid =(l+r)>>1;
if(check(mid)>=m) l=mid;
else r=mid;
}
cout << l << '\n';
return 0;
}