题目链接
题目思路
本质上就是利用线段树上二分的思维但是没有用线段树而已
最关键的是如何证明这样的查询次数少于(6e4)次
由于节点是(1e5)个
那么这颗线段树的深度最多(18)
最坏的情况是深度(14)全部占满那么查询的次数就是(2^{14}-1)
而最多(1e4)次查询下面四层节点最多查询(4)个
那么最多查询(4e4+2^{14}-1)
代码
#include<bits/stdc++.h>
#define debug printf("
I am here
");
#define fi first
#define se second
#define pii pair<int,int>
typedef long long ll;
const int maxn=2e3+5,inf=0x3f3f3f3f,mod=1e9+7;
const ll INF=0x3f3f3f3f3f3f3f3f;
using namespace std;
int n,t;
int k;
map<pair<int,int>,int> mp;
int cal(int l,int r){
if(mp.count({l,r})) return mp[{l,r}];
printf("? %d %d
",l,r);
fflush(stdout);
int re;
scanf("%d",&re);
mp[{l,r}]=r-l+1-re;
return mp[{l,r}];
}
void query(int l,int r,int k){
mp[{l,r}]--;
if(l==r){
printf("! %d
",l);
fflush(stdout);
return ;
}
int mid=(l+r)/2;
if(cal(l,mid)>=k) query(l,mid,k);
else query(mid+1,r,k-cal(l,mid));
}
int main(){
scanf("%d%d",&n,&t);
while(t--){
scanf("%d",&k);
query(1,n,k);
}
return 0;
}