一个有点烦的 \(8\log n\) 的做法。
大致想法大家都一样:以 \(1\) 为根,然后先问出每个点深度,再问出每个点的父亲。
首先先用一个 log 的做法问出树高,具体做法是直接令根节点的 \(f\) 为二分出的 \(mid\),看能否覆盖所有点即可,记最大深度为 \(mxdep\)。可以在二分过程中顺带着求出深度为 \(mxdep\) 的点集。
先考虑怎么问每个点的深度,我们分层,假设现在已经对于每个 \(i\in[0,\dfrac{mxdep}{2^k}]\) 已经知道了哪些点深度在 \([i·2^k,(i+1)·2^k-1]\) 这段区间内,以及深度等于 \(i·2^k,(i+1)·2^k-1\) 的点有哪些(方便起见,我们记这三个信息分别为 \(st_i,top_i,bot_i\))。考虑如何将这些长度为 \(2^k\) 的大区间划分为 \(2^{k-1}\) 的小区间(即,对于每个 \(i\in[0,\dfrac{mxdep}{2^{k-1}}]\) 求出深度在 \([i·2^{k-1},(i+1)·2^{k-1}-1]\) 的点中的点 \(st'_i\),\(top'_i,bot'_i\) 的定义类似),我们先对于每个 \(i\in[0,\dfrac{mxdep}{2^k}]\) 且是偶数的 \(i\),令 \(top_i\) 中点的 \(f\) 为 \(2^{k-1}-1\),其他点的 \(f\) 为零,这样,对于偶数 \(i\),\(st_i\) 中那些被覆盖的点的深度就在 \(st'_{2i}\) 中,没被覆盖的点的深度就在 \(st'_{2i+1}\) 中。对于奇数也同样处理。这样我们求出了 \(st'\),但是我们还不知道 \(top'\) 和 \(bot'\)。考虑对于每个 \(i\in\mathbb{Z}\),将 \(st'_{2i}\) 中的点的 \(f\) 设为 \(1\),其他点的 \(f\) 为 \(0\),这样对于 \(st_{2i+1}\) 中的所有点,那些被覆盖的点要么在 \(top'_{2i+1}\) 中,要么在 \(bot'_{2i+1}\) 中,而显然 \(bot'_{2i+1}=bot_i\),因此可以求出 \(top'_{2i+1}\),同时因为 \(top'_{2i}=top_i\),这样可以知道所有 \(top'\)。接下来考虑怎么求 \(bot'\),我们将 \(top'_{2i}\) 的点的 \(f\) 都设为 \(2^{k-1}-2\),这样 \(st'_{2i}\) 中没被覆盖的点就一定在 \(bot'_{2i}\) 中,再根据 \(bot'_{2i+1}=bot_i\) 求出所有 \(bot'\)。这样我们使用了 \(4\) 次询问从第 \(k\) 层推到第 \(k-1\) 层。总询问次数 \(4\log n\)。
接下来考虑怎么求每个点的父亲,这部分其实还挺 trivial,对于 \(k=0,1,2\),我们每次给深度 \(\bmod 3=k\) 的点确定父亲,这个模型相当于我们有两组集合 \(S_i,T_i\),我们已经确定 \(T_i\) 中每个点的父亲都在 \(S_i\) 中。考虑如何划分为更小的子问题,显然 \(|S_i|=1\) 的点直接已经确定了,否则令 \(S_i\) 中前一半元素的 \(f\) 为 \(1\),这样 \(T_i\) 中被覆盖的点的父亲就在 \(S_i\) 中,没被覆盖就在后一半,继续递归即可。又因为我们对 \(\bmod 3\) 进行了分组,因此不同组的询问不会影响。这样单次需要 \(\log n\) 个询问,而我们要跑三次,所以是 \(3\log n\)。
总共是 \(8\log n\)。代码实现起来有点细节。
const int MAXN=1000;
int n;
vector<bool>query(vector<int>v){
printf("?");for(int x:v)printf(" %d",x);printf("\n");fflush(stdout);
string s;cin>>s;vector<bool>res(n);
for(int i=0;i<n;i++)res[i]=s[i]-'0';
for(int i=0;i<n;i++)if(v[i])res[i]=1;
return res;
}
int dep[MAXN+5],fa[MAXN+5],mxdep;vector<int>qv[MAXN+5];
void calc_dep(vector<tuple<vector<int>,vector<int>,vector<int> > >v,int k){
//(total,top,bottom)
if(k==0){for(int i=0;i<v.size();i++)for(int x:get<0>(v[i]))dep[x]=i;return;}
if(k==1){
for(int i=0;i<v.size();i++){
for(int x:get<1>(v[i]))dep[x]=i*2;
for(int x:get<2>(v[i]))dep[x]=i*2+1;
}return;
}
vector<tuple<vector<int>,vector<int>,vector<int> > >nv;
vector<int>vec(n);vector<bool>tmp,res(n);
for(int i=0;i<v.size();i+=2)for(int x:get<1>(v[i]))vec[x]=((1<<k-1)-1);
tmp=query(vec);
for(int i=0;i<v.size();i+=2)for(int x:get<0>(v[i]))if(tmp[x])res[x]=1;
for(int i=0;i<n;i++)vec[i]=0;
for(int i=1;i<v.size();i+=2)for(int x:get<1>(v[i]))vec[x]=((1<<k-1)-1);
tmp=query(vec);
for(int i=1;i<v.size();i+=2)for(int x:get<0>(v[i]))if(tmp[x])res[x]=1;
for(int i=0;i<v.size();i++){
vector<int>v0,v1;
for(int x:get<0>(v[i])){
if(res[x]==0)v0.pb(x);
else v1.pb(x);
}
if(!v0.empty()){
nv.pb(mt(v1,get<1>(v[i]),vector<int>{}));
nv.pb(mt(v0,vector<int>{},get<2>(v[i])));
}else nv.pb(mt(v1,get<1>(v[i]),get<2>(v[i])));
}
for(int i=0;i<n;i++)vec[i]=0;
for(int i=0;i<nv.size();i+=2)for(int x:get<0>(nv[i]))vec[x]=1;
res=query(vec);
for(int i=1;i<nv.size();i+=2){
static bool vis[MAXN+5];memset(vis,0,sizeof(vis));
vector<int>vv;
for(int x:get<2>(nv[i]))vis[x]=1;
for(int x:get<0>(nv[i]))if(res[x]&&!vis[x])vv.pb(x);
get<1>(nv[i])=vv;
}
for(int i=0;i<n;i++)vec[i]=0;
for(int i=0;i<nv.size();i+=2)for(int x:get<1>(nv[i]))vec[x]=(1<<(k-1))-2;
res=query(vec);
for(int i=0;i<nv.size();i+=2){
static bool vis[MAXN+5];memset(vis,0,sizeof(vis));
vector<int>vv;
for(int x:get<1>(nv[i]))vis[x]=1;
for(int x:get<0>(nv[i]))if(!res[x]&&!vis[x])vv.pb(x);
if(get<2>(nv[i]).empty())get<2>(nv[i])=vv;
}
calc_dep(nv,k-1);
}
void calc_fa(vector<pair<vector<int>,vector<int> > >_v){
vector<pair<vector<int>,vector<int> > >v,nv;
for(auto t:_v){
if(t.fi.size()==1){for(int x:t.se)fa[x]=t.fi[0];}
else v.pb(t);
}
if(v.empty())return;
vector<int>vec(n);vector<bool>res;
for(int i=0;i<v.size();i++){
int mid=v[i].fi.size()/2;
for(int j=0;j<mid;j++)vec[v[i].fi[j]]=1;
}res=query(vec);
for(int i=0;i<v.size();i++){
vector<int>A,B;int mid=v[i].fi.size()/2;
for(int j=0;j<mid;j++)A.pb(v[i].fi[j]);
for(int x:v[i].se)if(res[x]==1)B.pb(x);
nv.pb(mp(A,B));A.clear();B.clear();
for(int j=mid;j<v[i].fi.size();j++)A.pb(v[i].fi[j]);
for(int x:v[i].se)if(res[x]==0)B.pb(x);
nv.pb(mp(A,B));
}calc_fa(nv);
}
int main(){
scanf("%d",&n);
int l=0,r=n-1;vector<int>bot;
while(l<=r){
int mid=l+r>>1;vector<int>v(n);v[0]=mid;
vector<bool>res=query(v);vector<int>v0;
for(int i=0;i<n;i++)if(!res[i])v0.pb(i);
if(v0.empty())r=mid-1;
else mxdep=mid,l=mid+1,bot=v0;
}
mxdep++;int K=0;while((1<<K)<=mxdep)++K;
if(mxdep==1){printf("!\n");for(int i=2;i<=n;i++)printf("1 %d\n",i);fflush(stdout);return 0;}
vector<int>vec;for(int i=0;i<n;i++)vec.pb(i);
calc_dep({mt(vec,vector<int>{0},bot)},K);
for(int x:bot)dep[x]=mxdep;
for(int i=0;i<n;i++)qv[dep[i]].pb(i);
for(int i=0;i<3;i++){
vector<pair<vector<int>,vector<int> > >v;
for(int j=i;j<mxdep;j+=3)v.pb(mp(qv[j],qv[j+1]));
calc_fa(v);
}
printf("!\n");
for(int i=1;i<n;i++)printf("%d %d\n",fa[i]+1,i+1);
fflush(stdout);
return 0;
}
标签:vector,1158E,get,int,bot,Strange,device,2i,nv
From: https://www.cnblogs.com/tzcwk/p/Codeforces-1158E.html