题意
- 有n个数字,数字范围为1~n且不重复。
- 有数字流传输过来,你预先不知道其位置,但是你可以在接收数字之前给其定下位置。
- 问:你能否在确定小于等于100个数字位置之前找到一个数字,这个数字 a[i] 满足 a[i]<min(a[i-1],a[i+1])。(a[0]=a[n+1]= ∞)
解题思路
- 数据范围n为10^5,通过线性输入肯定无法解题,因为前100个数字不一定有满足题意的数字。
- 所以想到了二分法,10^5 采用二分法,只用二分 16 次。
- 要想找到满足题意的数字,需要运用极值存在的充分条件——区间左端递减右端递增,则区间内一定存在极小值点。(虽然题目中的点是离散的,但是可以类比)。如图中(2)
- 不断二分,让区间 [l,r] 总是满足 a[l-1]>a[l] 且 a[r]<a[r+1] 。
![](https://img2020.cnblogs.com/blog/1218254/202102/1218254-20210208151006239-1352711018.png)
注意
- 这题最难的地方在于不是常规的输入输出,你并不能一次性输入所有n个数字,然后判断得出结果。(通过强行让你flush实现)
C++ Code
#include <iostream>
using namespace std;
int a[100010];
int main() {
int n;
cin >> n;
int l = 1;
int r = n;
while(l < r){
int m = (l+r)/2;
cout << "? " << m << endl << flush;
cout << "? " << m+1 << endl << flush;
cin >> a[m] >> a[m+1];
if(a[m] < a[m+1]){
r = m;
}else{
l = m+1;
}
}
// 此时l与r相等,输出l或r都可。
cout << "! " << l << endl;
return 0;
}