题解我就是不交到洛谷上!

交互题普遍难度虚高。

这种大便交互题一般有个特别逆天的常数,在这道题上是 $420$。

你考虑那个大常数咋用。

我们发现每次询问的本质是树上到 $u,v,w$ 距离的和最小的节点。

你考虑一个节点被作为答案回答的次数,发现如果这个点的三棵子树的大小为 $a,b,c$ (不足三棵子树的用 $0$ 补全),那么答案就是:$a\times b\times c$。

然后你发现一个很显然的事实,就是你发现出现次数最多的点,是根节点的两棵子树的根。

如果我们得到了那两个根(设为 $r_1,r_2$),那么就可以直接询问 $n-2$ 遍 $(r_1,r_2,i)$,当回答的是 $i$ 的时候,那个 $i$ 就是根,直接输出就行了,证明是显然的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<bits/stdc++.h>
using namespace std;
mt19937 rd((unsigned long long)new char);
int n,h,cnt[1000005],cnt2[1000005];
int main(){
cin>>h;n=(1<<h)-1;
for(int i=1;i<=420;++i){
int x=rd()%n+1,y=rd()%n+1;
while(y==x)y=rd()%n+1;
int z=rd()%n+1;
while(z==x||z==y)z=rd()%n+1;
cout<<"? "<<x<<' '<<y<<' '<<z<<endl;
int t;cin>>t;++cnt[t];
}
int mx1=-1,mx2=-2,id1=0,id2=0;
for(int i=1;i<=n;++i){
if(cnt[i]>mx1)mx2=mx1,mx1=cnt[i],id2=id1,id1=i;
else if(cnt[i]>mx2)mx2=cnt[i],id2=i;
}
for(int i=1;i<=n;++i){
if(id1==i||id2==i)continue;
cout<<"? "<<id1<<' '<<id2<<' '<<i<<endl;
int x;cin>>x;
if(x==i){cout<<"! "<<x<<endl;return 0;}
}
return 0;
}