算法基础课笔记and题解汇总
笔记:
整数二分
听说只有10%的程序员能写对二分?
这似乎是真的。。。
因为二分看起来简单,实际上有很多细节问题。
二分的本质
给定一个区间,在它上面定义某种性质,使得这种性质在右半部分满足,在左半部分不满足。二分可以用来寻找这个性质的边界。
二分的本质不是单调性,但是有单调性一定可以用二分,没有单调性有可能可以用二分。
有点绕。
求左半部分分界点:
mid=(l+r+1)/2
这部分为什么要+1呢?
先假设不+1:
设l=r−1,那么就会死循环,因为mid=l,然后更新l=mid=l。
-
if(check(mid))
- mid在左部分,ans:[mid,r],l=mid。
-
else
- mid在右部分,ans:[l,mid−1],r=mid−1。
求右半部分分界点:
mid=(l+r)/2
-
if(check(mid))
- mid在右部分,ans:[l,mid],r=mid。
-
else
- mid在左部分,ans:[mid+1,r],l=mid+1。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int n, m, a[N];
int main() {
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++) scanf("%d", &a[i]);
while (m--) {
int x; scanf("%d", &x);
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r >> 1;
if (a[mid] >= x) r = mid;
else l = mid + 1;
}
if (a[l] != x) cout << "-1 -1" << endl;
else {
printf("%d ", l);
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (a[mid] <= x) l = mid;
else r = mid - 1;
}
printf("%d\n", l);
}
}
return 0;
}