题解 逃离藏宝洞
首先发现(除了第一次)每个点一定知道是从哪边过来的
那么一次询问至少能让深度上升 1
再考虑怎么让深度多上升一些
那么多走几步之后可以通过始/终深度得到 lca 的深度
那么走 \(k\) 步期望上升 \(\frac{1}{2}\times 1+\frac{1}{4}\times 2+\frac{1}{8}\times 3+\cdots \approx2\)
那么可以用大约 \(\frac{d}{2}\) 步回到地面
点击查看代码
#include "escape.h"
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
int k=40;
int sta[N], rest[3][3], top;
random_device seed;
mt19937 rnd(seed());
void solve(int dep, int back) {
// cout<<"solve: "<<dep<<' '<<back<<endl;
int dir[2], now; top=0;
sta[0]=back;
for (int i=1; i<=k; ++i) {
now=0;
for (int j=0; j<3; ++j) if (j!=sta[top]) dir[now++]=j;
move(sta[++top]=dir[rnd()&1]);
}
int d=query();
if (d==dep+k) solve(d, sta[top]);
else {
int t=(k-(dep-d))/2;
while (top>t) move(sta[top--]);
int v=rest[sta[top]][sta[top+1]];
move(v);
solve(dep+t+1, v);
}
}
void escape(int lm, int lq) {
if (lm==3002) k=1;
rest[0][1]=rest[1][0]=2;
rest[1][2]=rest[2][1]=0;
rest[0][2]=rest[2][0]=1;
int d=query();
move(0);
if (query()>d) solve(d+1, 0);
move(0);
move(1);
if (query()>d) solve(d+1, 1);
move(1);
move(2);
solve(d+1, 2);
}