【LOJ#6669】Nauuo and Binary Tree

1|0题目


题目链接:https://loj.ac/p/6669
这是一道交互题。

Nauuo 是一个喜欢二叉树的女孩子。

这天,她创造了一个有 n 个节点的二叉树。节点的编号从 1n,其中 1 是二叉树的根节点。

不过,她不记得这棵二叉树具体长什么样子了,她只记录了二叉树上任意两个节点之间的距离。你可以通过向她询问有关距离的信息来还原这棵二叉树,两个节点之间的距离定义为它们之间最短路上的边数。

你可以向 Nauuo 询问不超过 30000 次有关距离的信息。你只需要告诉她 2n 号节点的父亲的编号就可以了。

n3000

2|0思路


先用 n1 次询问得出每一个点的深度。然后从小到大枚举深度。
假设我们枚举到深度 i,那么我们已经构建出深度为 1i1 的点的二叉树了。我们先将这棵树 dfs 一遍并重剖。
然后依次枚举深度为 i 的点 x。先令 y1 号节点,询问 y 所在重链深度最深的节点 zx 之间的距离。根据 depx+depz2deplca(x,y)=dis(x,z),可以得到 lca(x,z) 的深度。
由于这个 lca(x,z) 一定在 y 所在重链上,而一条重链上的点深度两两不同,所以我们可以确定点 lca(x,z)
由于这是一棵二叉树,而且 x 一定和 z 分别位于 lca(x,z) 的两棵子树内,所以我们可以确定 x 的一个祖先是 lca(x,z)z 所在子树外的另一棵子树。那么我们就令 y 等于这棵子树的根节点,继续上述操作直到 depy=depx1 即可。
根据重链剖分的性质,一个点向上的轻链数量是 O(logn) 的,所以我们操作次数是 O(n+nlogn) 的。由于树剖常数很小,所以可以通过 30000 次的限制。
时间复杂度 O(n2)

3|0代码


#include <bits/stdc++.h> using namespace std; const int N=3010; int n,fa[N],bot[N],size[N],dep[N],ch[N][2]; vector<int> pos[N]; void dfs(int x) { size[x]=1; bot[x]=x; if (ch[x][0]) { dfs(ch[x][0]); size[x]+=size[ch[x][0]]; } if (ch[x][1]) { dfs(ch[x][1]); size[x]+=size[ch[x][1]]; if (size[ch[x][1]]>size[ch[x][0]]) swap(ch[x][0],ch[x][1]); } if (ch[x][0]) bot[x]=bot[ch[x][0]]; } void add(int from,int to) { fa[to]=from; if (ch[from][0]) ch[from][1]=to; else ch[from][0]=to; } void solve(int x) { int y=1,dis; while (dep[y]!=dep[x]-1) { printf("? %d %d\n",x,bot[y]); fflush(stdout); scanf("%d",&dis); dis=(dep[x]+dep[bot[y]]-dis)/2; while (dep[y]<dis) y=ch[y][0]; if (dep[y]==dep[x]-1) break; y=ch[y][1]; } add(y,x); } int main() { scanf("%d",&n); for (int i=2;i<=n;i++) { printf("? 1 %d\n",i); fflush(stdout); scanf("%d",&dep[i]); pos[dep[i]].push_back(i); } for (int i=1;i<=n;i++) { dfs(1); for (int j=0;j<pos[i].size();j++) solve(pos[i][j]); } printf("!"); for (int i=2;i<=n;i++) printf(" %d",fa[i]); printf("\n"); fflush(stdout); return 0; }

__EOF__

本文作者stoorz
本文链接https://www.cnblogs.com/stoorz/p/14214485.html
关于博主:菜死了 /fad
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   stoorz  阅读(750)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示