【题解】 CF1486C2 Guessing the Greatest (hard version)

题面传送门

解决思路

看到 1e5 的范围和 20 次询问,容易想到二分。

所以考虑如何来二分。

首先,可以询问一次 [1,n],得到所有数中的次小值位置 x ,然后可以问一次 [1,x] 得出最大值在 x 的左侧还是右侧。

然后再确定的区间里进行二分。以左边为例,初始 l=1,r=x,每次询问 [mid,x],若次大值仍是 x,则说明最大值在 [mid,x] 区间内,将 l 更新,反之则在另一边,将 r 更新。右边同理,每次询问每 [x,mid] 即可。同时,每当 x 仍是次大值时,将 ans 更新成 mid,最后得到的就是答案了。

注意一个细节:当第一次询问结果为 1 时,可以直接判定最大值在右区间,否则询问 [1,1] 会出错。

AC Code

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
#define TIE cin.tie(0),cout.tie(0)
using namespace std;
int n,l,r,x,y,mid,ans;
bool fl;
void binary(int l,int r,int typ){
	while(l<=r){
		mid=(l+r)>>1;
		int _1=min(x,mid),_2=x+mid-_1;
		cout<<"? "<<_1<<" "<<_2<<endl;
		cin>>y;
		if((x==y)^typ) l=mid+1;   //两种情况放一起了
		else r=mid-1;
		if(x==y) ans=mid;  //更新ans
	}
}
signed main(){
	cin>>n;
	cout<<"? 1 "<<n<<endl;
	cin>>x;
	if(x!=1){
		cout<<"? 1 "<<x<<endl;
		cin>>y;
		if(y!=x) fl=1;
	}
	else fl=1;
	if(fl) binary(x+1,n,1);
	else binary(1,x-1,0);
	cout<<"! "<<ans<<endl;
	return 0;
}
posted @   Binary_Lee  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
Title
点击右上角即可分享
微信分享提示