二分查找及其应用

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

给定一个有序序列a0,a1,a2...aN, 给出一个目标值tg,在序列中查找 是否存在tg,如果存在,返回tg的 下标。
如何快速查找?
我们必须看到数列是有序的
• 充分利用有序的条件,类似猜 数一样查找tg。
• 复杂度为log(n)。 • 那么我们来看看如何实现二分
查找。
int bs(int *a, int n, int tg) { int l = 0, r = n-1; while(l <= r) { int mid = (l+r)/2; if(a[mid] == tg) return mid; else if(a[mid] > tg) r = mid-1; else l = mid+1; } return -1;
总复杂度O(n*log(INF))
int n, c;
int main()
int pos[maxn];
{
bool ok(int ma) {
cin >> n >> c;
int cnt = 1;
for(int i = 0; i < n; i++)
int last = 0;
cin >> pos[i];
for(int i = 1; i < n; i++) {
num += (int) (a[i]/x);
double l = 0, r = 100001;
}
for(int i = 0; i < 100; i++) {
if(num >= k) return true;
double m = (l+r)/2;
return false;
if(ok(m)) l = m;
条件限制: 2<=N<=100000 2<=M<=N 0<=xi<=10^9
样例输入 N=5, M=3, x={1,2,8,4,9}
样例输出 3
(在位置1,4,9放3头牛)
另C(d):=可以安排的牛的位置使 得最近的两头牛的 距离 不小于d
问题就变成了求满足C(d)的最大 的d。
每次判断对每头牛最多处理一次 ,因此判断的复杂度是O(n)
sort(pos, pos+n);
if(pos[i] - pos[last] < ma) int l = 0, r = MAX+1;
continue;
while(r - l > 1) {
cnt++;
int m = (l+r) >> 1;
last = i;Baidu Nhomakorabea
if(ok(m)) l = m;
}
else r = m;
• 那么下一次B该猜什么。。。
大家已经发现,问题变成了5011000之间猜一个数,那么应该猜
(501+1000)/2 = 750! 如果运气还是不好,,又猜小了. 没关系!只猜了仅仅两次,我们 就将区间缩小为 751--1000. 那么继续下去...
我们发现,每次可以将区间缩小 为原来的一半。递减速度显然就 是log级别的。 log(1000)向上取整只有10. 那么我们一定可以在10次之内猜 出这个数。
最坏情况下需要多少次呢?
最坏情况下, ElemenT也不用超过 十次可以猜出!
看起来好厉害的样子
• 其实并不是,下面将引入“二 分搜索”的概念。
• 如上述的游戏中,第一次应该 取多少呢?
• 500! • 很不巧并不是500,而是一个比
500大的数。 • 虽然运气不好,但是B将区间
的范围砍掉了一半!
if(cnt >= c) return true;
}
return false;
cout << l << endl;
}
return 0;
}
大家还有什么疑问吗?
Thank you! 祝大家周日 月赛取得好成绩! 奖品丰厚呦~
题!
int n, k;
int main()
double a[maxn], tot = 0; {
bool ok(double x) {
cin >> n >> k;
int num = 0;
for(int i = 0; i < n; i++)
for(int i = 0; i < n; i++) {
cin >> a[i];
}
二分查找的应用(二分答案)
• 假定一个解判断是否可行 • 最大化最小值 • 最大化平均值
有N条绳子,它们长度分别为Li。如果 从他们中切割出K条长度相同的绳子的 话,这K条绳子每条最长能有多长?答 案保留两位小数。
• 1<=N<=10^4, 1<=K<=10^4, 1<=Li<=10^5
• 样例输入
• N = 4, K = 11, L={8.02, 7.43, 4.57, 5.39}
• 样例输出
• 2.00(每条绳子可以得到4,3,2,2共计 11条)
另C(x):=可以得到K条长度为x的绳子
• 问题转化为求 满足C(x)条件的最大 的x。
• C(x) = ( Li/x 的总和是否大于K) • 因此,计算C(x)的复杂度是O(n) • 那么 只要二分枚举x,就可以解决此
二分查找及其应用
— By ElemenT
请在这里输入您的标题
NO!
今天,你AC了吗?
YES!
刷题太无聊?我们玩游戏吧!
相信大家都玩过猜数字的 游戏。两人游戏,A同学在心 里默念一个整数n (1 <= n <= 1000)。 B同学猜n是多少。 同时如果B没有猜对,A告诉 他这个数比默念的数高了还 是低了。
}
else r = m;
}
printf("%.2f\n", 0.01 * (int)(l*100) );
return 0;
}
再看一道最大化最小值的例题
这类问题通过二分搜索可以很好 的解决。
农夫约翰搭了一间有N间牛社的
小屋。牛舍排在一条直线上 ,第i号牛舍在xi的位置,但 是他的M头小牛对小屋很不 满意,因此经常互相攻击。 约翰为了防止牛之间互相伤 害,因此决定把每头牛都放 在离其他牛尽可能远的牛舍 。也就是最大化最近的两头 牛之间的距离。
相关文档
最新文档