Loading... ## 求左端点: ```cpp //求左端点 int l = 0, r = n - 1; while(l < r){ int mid = l + r >> 1; if(arr[mid] >= x) r = mid; else l = mid + 1; } ``` ## 求右端点: ```cpp //求右端点 l = 0, r = n - 1; while(l < r){ int mid = l + r + 1 >> 1; if(arr[mid] <= x) l = mid; else r = mid - 1; } ``` ## 例题: <div class="tip inlineBlock success"> 给定一个按照升序排列的长度为 **n** 的整数数组,以及 **q** 个查询。 对于每个查询,返回一个元素 **k** 的起始位置和终止位置(位置从 **0** 开始计数)。 如果数组中不存在该元素,则返回 `-1 -1`。 #### 输入格式 第一行包含整数 **n** 和 **q**,表示数组长度和询问个数。 第二行包含 **n** 个整数(均在 **1**∼**10000**∼10000 范围内),表示完整数组。 接下来 **q** 行,每行包含一个整数 **k**,表示一个询问元素。 #### 输出格式 共 **q** 行,每行包含两个整数,表示所求元素的起始位置和终止位置。 如果数组中不存在该元素,则返回 `-1 -1`。 #### 数据范围 **1**≤****n****≤**100000**≤n≤100000 **1**≤****q****≤**100001≤q≤10000 **1****≤****k****≤100001≤k≤10000 #### 输入样例: ``` 6 3 1 2 2 3 3 4 3 4 5 ``` #### 输出样例: ``` 3 4 5 5 -1 -1 ``` </div> ### 题解: ```cpp #include <bits/stdc++.h> using namespace std; const int N = 100000 + 10; int arr[N]; int main(){ int n, m; cin >> n >> m; for(int i = 0; i < n; i++) cin >> arr[i]; while(m --){ int x; cin >> x; //求左端点 int l = 0, r = n - 1; while(l < r){ int mid = l + r >> 1; if(arr[mid] >= x) r = mid; else l = mid + 1; } if(arr[l] != x) cout << -1 << " "; else cout << l << " "; //求右端点 l = 0, r = n - 1; while(l < r){ int mid = l + r + 1 >> 1; if(arr[mid] <= x) l = mid; else r = mid - 1; } if(arr[r] != x) cout << -1 << " "; else cout << r << " "; cout << endl; } return 0; } ``` . 最后修改:2022 年 04 月 08 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果文章有用,请随意打赏。
1 条评论
总所周知,二分是一个奇妙的东西。