ZMQ_Ink6556
2024-11-15 15:15:47
有一个值均不同的数组,每次你可以询问一个子段次大值的位置,请你在
首先,我们确定全局次大值的位置,询问
此时我们在答案区间中二分,为避免区间只有一个数的情况:
如果询问
因为四种情况打了四个不太相同的二分,所以马蜂有点史,请见谅。
#include <bits/stdc++.h>
using namespace std;
int n , l , r , mid , ans , sec;
inline bool ask(int q)
{
int x;
cout << "? " << min(sec , q) << ' ' << max(sec , q) << endl;
cin >> x;
return x == sec;
}
int main()
{
cin >> n;
cout << "? 1 " << n << endl;
cin >> sec;
if(sec == 1)
{
l = 2;
r = n;
while(l <= r)
{
if(l == r)
{
ans = l;
l++;
continue;
}
mid = (l + r) / 2;
if(mid == r)
{
mid--;
}
if(ask(mid))
{
ans = mid;
r = mid;
}
else
{
l = mid + 1;
}
}
}
else if(sec == n)
{
l = 1;
r = n - 1;
while(l <= r)
{
if(l == r)
{
ans = l;
l++;
continue;
}
mid = (l + r + 1) / 2;
if(mid == l)
{
mid++;
}
if(ask(mid))
{
ans = mid;
l = mid;
}
else
{
r = mid - 1;
}
}
}
else
{
cout << "? 1 " << sec << endl;
cin >> ans;
if(ans == sec)
{
l = 1;
r = sec - 1;
while(l <= r)
{
if(l == r)
{
ans = l;
l++;
continue;
}
mid = (l + r + 1) / 2;
if(mid == l)
{
mid++;
}
if(ask(mid))
{
ans = mid;
l = mid;
}
else
{
r = mid - 1;
}
}
}
else
{
l = sec + 1;
r = n;
while(l <= r)
{
if(l == r)
{
ans = l;
l++;
continue;
}
mid = (l + r) / 2;
if(mid == r)
{
mid--;
}
if(ask(mid))
{
ans = mid;
r = mid;
}
else
{
l = mid + 1;
}
}
}
}
cout << "! " << ans;
return 0;
}
双倍经验:CF1486C1。