题解:P15551 Get MiN? Get MeX! 加强版
NikaidouHiro · · 题解
我们当然希望能直接用二分找出来
不妨三分。对于当前三个段
直接三分肯定是不行的,因为我们可能会把区间剁开,导致无法询问。所以采用另一种方法:选择当前两个区间中最大的一个剁成两半。这样区间总长最多两次划分就变为一半。划分到最后会剩下两个长度恰好为
每次询问我们只需要知道两个区间的答案,因此直接做就是
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
inline int query(int l,int r){
cout<<"? 1 "<<l<<" "<<r<<endl;
int res;return cin>>res,res;
}
int n;
int main(){
cin>>n;if(n==1)return cout<<"! 1"<<endl,0;
int l1=1,r1=n>>1,w1=-1,l2=r1+1,r2=n,w2=-1;
for(;;){
if(l1==r1&&l2==r2)break;
if(r1-l1<r2-l2)swap(l1,l2),swap(r1,r2),swap(w1,w2);
int mid=l1+r1>>1;
if(!~w2)w2=query(l2,r2);
int x=query(l1,mid);
if(x==w2)w1=x,r1=mid;
else if(x>w2)w1=w2,l1=mid+1;
else w1=w2=x,l2=mid+1,r2=r1,r1=mid;
}
cout<<"? 2 "<<l1<<" "<<r1<<endl;
int x;cin>>x,cout<<"! "<<(x==1?l2:l1)<<endl;
return 0;
}