[BalticOI 2020 Day1] 染色
非常有意思的交互题。
隐藏一个常数
根据数据范围我们可以知道需要一个严格
那么只有倍增和二分两个选择。
倍增每次往一个方向走,如果来回走显然会重复位置,看上去就非常不可做。
考虑二分。由于
到这里我们也没有想到什么好的方法能避免重复询问。
倒着想,最坏的情况我们一定要判断
这样我们就知道了最后两次的询问,并且如果卡到最坏情况,显然
所以我们可以反推出第一次询问的位置,并且这个位置是唯一的。
从初始位置出发,每次交替向左或向右跳
但是这样做为什么不会有重复的,因为我们倒着推出这个方案是唯一的,其余方案显然会被
感性理解一下,如果一直返回
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define int long long
using namespace std;
vector<int>c;
int ask(int x){
cout<<"? "<<x<<endl;
int op;cin>>op;
return op;
}
signed main(){
int T;scanf("%lld",&T);
while(T--){
int n;scanf("%lld",&n);
c.clear();
int l = 1, r = n - 1;
while(l <= r){
int mid = (l + r) >> 1;
c.push_back(mid);
l = mid + 1;
}
reverse(c.begin(), c.end());
int st = 1, j = 1;
for(int x : c)st += j * x, j *= -1;
l = 1, r = n - 1;int ed = n;
ask(st);
while(l <= r){
int mid = (l + r) >> 1;
st += j * mid, j *= -1;
if(ask(st))ed = mid, r = mid - 1;
else l = mid + 1;
}
cout<<"= "<<ed<<endl;
}
return 0;
}