标签:over data- ble minus false element pos user wrap
https://codeforces.com/contest/1174/problem/F
题意: 交互题,给出一棵树,1为树根,有一点x为目标点。
有两种操作 d a: 询问a到x的距离,s a:询问从a到x的路径上第二个结点的编号,注意a必须要是x的祖先结点。
需要在36次询问内给出x结点
思路:先从树根开始一次dfs,sz数组维护以i为根节点的树拥有的结点数(包括i本身)。 询问一次d 1,得到x的深度depx
然后从树根开始,每次经过sz值最大的子节点,直到该路径的终点v,并询问d v 得到dist(x,v).
因为我们现在知道depv,depx,dist(x,v),那么我们可以知道y=lca(v,x)的深度depy, dist(x,v)=depx+depv−2∗depy
因为该路径上的所有点深度都不同,所以我们可以得到y点的位置,询问s y,得到从y到x路径上第二个结点的编号。
进行下一次dfs,当depv==depx时,x的位置便是该次dfs上路径的唯一点。于是我们得到x的位置
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
vector<int> v[maxn],h;
int sz[maxn],dep[maxn],depx;
int pre(int node,int p){
sz[node]=1;
for(int u:v[node]){
if(u!=p){
dep[u]=dep[node]+1;
sz[node]+=pre(u,node);
}
}
return sz[node];
}
int query(char c,int u){
printf("%c %d\n",c,u);
fflush(stdout);
int ans;
scanf("%d",&ans);
return ans;
}
void get(int node){
h.push_back(node);
int big=-1;
for(int u:v[node]){
if(sz[node]>sz[u]&&(big==-1||(sz[u]>sz[big])))
big=u;
}
if(big!=-1) get(big);
}
int dfs(int node){
h.clear();
get(node);
int depy=(depx+dep[h.back()]-query