题意:有一个n*n的矩阵,a[i][j]>=a[i-1][j],a[i][j]>=a[i][j-1](每一行非递减,每一列非递减),每次可以查询a[i][j]是否小于等于x,如果返回1,否则返回0.输出操作,求第k小的最大数。
知识点:二分,暴力
分析:每次查询是否有k个数大于我们要求的这个数。
只要左上角面积大于等于k就符合条件,此时的x通过二分查询最大值
#include<bits/stdc++.h>
using namespace std;
int n,k;
bool query(int i,int j,int x){
cout<<"? "<<i<<" "<<j<<" "<<x<<endl;
int res;cin>>res;
if(res!=0)return true;//
else return false;
}
bool check(int x){
int cnt=0;//记录大于等于x的个数
int j=n;
for(int i=1;i<=n;i++){
while(j>=1&&!query(i,j,x)){//右上到左下
j--;//如果当前位置大于x,向左移动
}
cnt+=n-j;//加上第i行大于等于x的个数
}
return cnt>=k;//如果cnt>=k就是找到了(左上角的面积)
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n>>k;
int l=1,r=n*n;
int ans=0;
while(l<=r){//查找符合条件的最大值
int mid=(l+r)>>1;
if(check(mid)){
l=mid+1;
}
else{
r=mid-1;
ans=mid;
}
}
cout<<"! "<<ans<<endl;
return 0;
}