[PA2016] 寻踪 / Ciepło-zimno 题解
给 mashup 验了个题,简单来写一个题解。
在交互过程中,考虑缩小每一维的取值范围,不妨认为第
令每一维的值域为
考虑每次取出
这样的思路类似二分,可以近似地得出
但这种方法已经足够将最终所有的
询问次数是
放代码:
#include<bits/stdc++.h>
using namespace std;
struct info{
int p,l,r;
info(int p=0,int l=0,int r=0):p(p),l(l),r(r){}
inline bool operator <(const info &x)const{
return r-l<x.r-x.l;
}
};
int main(){
ios::sync_with_stdio(false);
int n,k,v; cin>>n>>k>>v;
vector<pair<int,int> > w(n,make_pair(0,v));
priority_queue<info> q;
for(int i=0;i<n;i++)
q.emplace(i,0,v);
while(q.top().r-q.top().l>1){
auto [p,l,r]=q.top(); q.pop();
cout<<"? ";
for(int i=0;i<n;i++){
if(i==p)cout<<l<<' ';
else cout<<(w[i].first+w[i].second>>1)<<' ';
}
cout<<endl;
int x; cin>>x;
cout<<"? ";
for(int i=0;i<n;i++){
if(i==p)cout<<r<<' ';
else cout<<(w[i].first+w[i].second>>1)<<' ';
}
cout<<endl;
if(cin>>x;x)w[p].first=(l+r>>1)+1;
else{
if(r-l+1&1)w[p].second=l+r>>1;
else w[p].second=(l+r>>1)+1;
}
q.emplace(p,w[p].first,w[p].second);
} // 每次取出 r[i]-l[i] 最大的 i 进行询问
for(int i=0;i<n;i++)
if(w[i].first<w[i].second){
if(w[i].second==v){
cout<<"? ";
for(int j=0;j<n;j++){
if(i==j)cout<<w[j].first-1<<' ';
else cout<<w[j].first<<' ';
}
cout<<endl;
int x; cin>>x;
cout<<"? ";
for(int j=0;j<n;j++){
if(i==j)cout<<w[j].second<<' ';
else cout<<w[j].first<<' ';
}
cout<<endl;
if(cin>>x;x)w[i].first=w[i].second;
else w[i].second=w[i].first;
}
else{
cout<<"? ";
for(int j=0;j<n;j++){
if(i==j)cout<<w[j].second+1<<' ';
else cout<<w[j].first<<' ';
}
cout<<endl;
int x; cin>>x;
cout<<"? ";
for(int j=0;j<n;j++){
if(i==j)cout<<w[j].first<<' ';
else cout<<w[j].first<<' ';
}
cout<<endl;
if(cin>>x;x)w[i].second=w[i].first;
else w[i].first=w[i].second;
}
} // 特殊处理 r[i]-l[i]=1 的 i
cout<<"! ";
for(auto i:w)cout<<i.first<<' ';
cout<<endl;
return 0;
}