对于easy情况的做法是,对每个范围都询问两次第二大值,借用第二大值确定最大值所在范围,然后缩小范围。
hard情况的做法是,先询问第二大值所在位置p,然后根据最大值所在其左还是右分情况进行二分,其比easy询问次数少了一半是因为每次问询都使用mid—p(假设最大值在p左边),如果第二大值位置还等于p,说明最大值位于mid—r范围内,使 l=mid,如果第二大值位置不等于p,说明最大值位置不位于mid—r范围内,使 r=mid-1,最大值在p右边的情况也类似。还要注意下不能询问范围为1的区间。
Code:
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int Max = 1e6 + 5;
ll x[Max], y[Max];
int main()
{
int l = 1, r, t=0;
cin >> r;
cout << "? 1" << " " << r << endl;
int p;cin >> p;
if (p != 1) {
cout << "? 1" << " " << p << endl;
cin >> t;
}
if (t == p)
{
r = p - 1;
while (l < r)
{
int mid = (l + r + 1) / 2;
cout << "? "<<mid << " " << p << endl;
cin >> t;
if (t == p)l = mid;
else r = mid - 1;
}
cout << "! " << l << endl;
}
else
{
l = p + 1;
while (l < r)
{
int mid = (l + r)/2;
cout << "? " << p << " " << mid << endl;
cin >> t;
if (t == p) r = mid;
else l = mid + 1;
}
cout << "! " << l << endl;
}
}