题解:CF1930H Interactive Mex Tree
好吧,我也不知道这是交互还是伪装成交互的构造了。

好吧,居然有图,我太强了。
由于是排列,所以可以把 \(\operatorname{mex}\) 转为补集的 \(\min\)。
在此图中,我们就是要用 \(5\) 个区间来覆盖 \(rt,A,B,C1,C2,D1,D2,E,F,G\) 这 \(10\) 个区域。
那么,先尝试使用 dfs 入栈序作为 \(p_1\)。
假设从左到右遍历这些边,这些部分在 dfs 序上连续的有 \((rt,A),(F),(C1),(C2,E),(D1),(D2,G,B)\)。
发现要用 \(6\) 次才行。
那么,考虑使用第二个序列。尝试使用出栈序来刻画。
这些部分在 dfs 出栈序上连续的有 \((A,F,C1),(C2),(E,D1),(D2),(G),(B,rt)\)。
权衡利弊得到最终策略:
入栈序:\((D2,G,B),(C2,E),(rt,A)\)。
出栈序:\((A,F,C1),(E,D1)\)。
实现:求 \(\operatorname{lca}\) 和 \(\operatorname{lca}\) 的两个儿子,另外,弄清楚出栈序和入栈序中 \(A,B,C1,C2,D1,D2,E,F,G,rt\) 对应的范围。实在不行看代码注释。
Plus:
还有可能 \(u\) 是 \(v\) 的祖先。

入栈连续的有 \((rt,A),(C1),(D1),(D2,C2,B)\)。
出栈连续的有 \((A,C1,D1),(D2),(C2),(B,rt)\)。
选择入栈 \((D2,C2,B),(rt,A)\)。
选择出栈 \((A,C1,D1)\)。
时间复杂度 \(O(q\log n)\)。
#include <bits/stdc++.h>
using namespace std;
const int N=100005;
int n,q,h[N],idx,e[N<<1],ne[N<<1];
int f1[N],g1[N],f2[N],g2[N],t1,t2;
int top[N],dep[N],sz[N],son[N],fa[N];//树剖
inline void add(int a,int b) {e[idx]=b,ne[idx]=h[a],h[a]=idx++;}
void dfs1(int u){
g1[f1[u]=++t1]=u;//入栈序
sz[u]=1,son[u]=0;
for (int i=h[u];i;i=ne[i]){
int v=e[i];
if (v==fa[u]) continue;
fa[v]=u,dep[v]=dep[u]+1;
dfs1(v),sz[u]+=sz[v];
if (sz[v]>sz[son[u]]) son[u]=v;
}
g2[f2[u]=++t2]=u;//出栈序
}
void dfs2(int u,int tp){
top[u]=tp;
if (son[u]) dfs2(son[u],tp);
for (int i=h[u];i;i=ne[i]){
int v=e[i];
if (v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
inline int LCA(int x,int y){
while (top[x]^top[y]) {
if (dep[top[x]]<dep[top[y]]) swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
inline int query(int t,int l,int r){//封装查询
if (l>r) return n;
cout<<"? "<<t<<" "<<l<<" "<<r<<endl;
int res;cin>>res;assert(res!=-1);
return res;
}
inline int MA(int x,int lca){//求lca到x上的lca的儿子
while (top[x]!=top[lca]){
if (fa[top[x]]==lca) return top[x];
x=fa[top[x]];
}
return son[lca];
}
inline void work(){
cin>>n>>q;idx=1;t1=t2=0;
for (int i=1;i<=n;i++) h[i]=0;
for (int i=1;i<n;i++){
int u,v;cin>>u>>v;
add(u,v),add(v,u);
}
dfs1(1),dfs2(1,1);
for (int i=1;i<=n;i++) cout<<g1[i]<<" ";cout<<endl;
for (int i=1;i<=n;i++) cout<<g2[i]<<" ";cout<<endl;
while (q--){
int u,v;cin>>u>>v;
if (f1[v]<f1[u]) swap(u,v);
int lca=LCA(u,v),res=n;
if (lca!=u){
int U=MA(u,lca),V=MA(v,lca);
res=min(res,query(1,f1[v]+1,n));//[D2,G,B]
res=min(res,query(1,f1[u]+1,f1[V]-1));//[C2,E]
res=min(res,query(1,1,f1[lca]-1));//[rt,A]
res=min(res,query(2,1,f2[u]-1));//[A,F,C1]
res=min(res,query(2,f2[U]+1,f2[v]-1));//[E,D1]
}
else {
res=min(res,query(1,f1[v]+1,n));//[D2,C2,B]
res=min(res,query(1,1,f1[u]-1));//[rt,u]
res=min(res,query(2,1,f2[v]-1));//[A,C1,D1]
}
cout<<"! "<<res<<endl;
cin>>res;//注意,这里要读入一个1!!!
}
}
int main(){
int T;cin>>T;
while (T--) work();
return 0;
}

浙公网安备 33010602011771号