前言
最近要考试了嘛,所以整整基础知识。
正文
二分查找
二分查找是 C++ 中的基础算法,在一个有序数列中查找一个数非常实用。
举个例子,在一个单调上升序列中找一个数(\(x\))的位置。
第一种方法,暴力一个个的找,复杂度 \(O(n)\)。
第二种方法,二分查找:二分查找顾名思义,先找到数列的中间下标 \(mid\)(查找方法:l/*左端点下标*/+r/*右端点下标*/>>1
),然后把 \(a_{mid}\) 与 \(x\) 比较看看它比 \(a_{mid}\) 大还是小,如果大就在 \(mid\) 的右边查找,代码实现:l=mid,mid=l+r>>1;
;如果小就在 \(mid\) 的左边查找,代码实现:r=mid,mid=l+r>>1;
。时间复杂度 \(O(\log n)\)。
例题代码就不给了。
二分答案
跟二分查找差不多,只不过这个是把已知答案范围二分,找到 \(mid\),再将 \(mid\) 代入函数中看看得出的答案比给出的答案大还是小,大就在 \(mid\) 的左边找,小就在 \(mid\) 的右边找。
例题代码(P1873):
#include <iostream>
#define ll long long
using namespace std;
int n,m;
ll h[10000001];
bool cmp(ll height) {
ll tot=0;
for (int i=1;i<=n;i++) {
if (h[i]>=height) {
tot+=h[i]-height;
}
}
return tot>=m;
}
int main() {
cin>>n>>m;
for (int i=1;i<=n;i++) {
cin>>h[i];
}
ll l=1,r=1e9,mid=0,ans=0;
while (l<=r) {
if (cmp(mid=l+r>>1)) {
ans=mid;
l=mid+1;
} else {
r=mid-1;
}
}
cout<<ans;
}
STL
STL 大法好!!
在 STL 中也有二分函数,分别为 upper_hound
,lower_hound
。
upper_hound
是查找首个大于给定元素的元素地址,lower_hound
是查找首个不小于给定元素的元素地址(记得是地址,所以一般用的时候要减去数组首地址)。
例题代码(P1020)
#include <algorithm>
#include <iostream>
using namespace std;
int n,cnt=1,cnt1=1;
int h[100001];
int f[100001],s[100001];
bool cmp(int a,int b) {
return a>b;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
n=1;
while (cin>>h[n]) {
n++;
}
n--;
f[1]=s[1]=h[1];
for (int i=2;i<=n;i++) {
if (f[cnt]>=h[i]) {
f[++cnt]=h[i];
} else {
f[upper_bound(f+1,f+cnt+1,h[i],cmp)-f]=h[i];
}
if (s[cnt1]<h[i]) {
s[++cnt1]=h[i];
} else {
s[lower_bound(s+1,s+cnt1+1,h[i])-s]=h[i];
}
}
cout<<cnt<<endl<<cnt1;
return 0;
}
finally
没了。