题目

有一棵大小为\(n\)只知道根节点为1的二叉树,

可以不超过\(3*10^4\)询问两点之间距离,

最后输出除了点1以外其余点的祖先

\(n\leq 3000\)


分析

\(O(n^2)\)的时间复杂度就可以了,主要是控制询问次数

首先将所有点的深度求出来,

那么询问按照点的深度递增去找该点的祖先,

有一个很重要的性质就是



通过询问可以将\(dep[x]+dep[y]-2*dep[LCA]\)求出来,由于\(dep[x]+dep[y]\)是确定的,那么\(LCA\)也可以求出来

由于\(dep[x],dep[y]\geq dep[LCA]\)所以只要按照深度一层一层找就可以询问\(x,y\)得到它们的\(LCA\)

若当前想要找的是\(x\)的祖先,那么只要找到一个合适的\(y\)让\(dep[x]=dep[LCA]+1\)即可以让\(LCA\)变成\(x\)的祖先,

那么一定让重新找\(y\)的次数最少,考虑树上的每条路径都可以被拆分成不超过\(O(\log n)\)条重链。

从根节点开始每次找重链然后如果LCA所对应的轻儿子存在那就跳到轻儿子,则总询问次数为\(O(n+n\log n)\)实际更小


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int N=3011;
int siz[N],son[N][2],foot[N],n,rk[N],dep[N],fat[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
bool cmp(int x,int y){return dep[x]<dep[y];}
inline signed Ask(int x,int y){
putchar(63),putchar(32),print(x),putchar(32),
print(y),putchar(10),fflush(stdout);
return iut();
}
inline void dfs1(int x){
siz[x]=1,foot[x]=x;
if (son[x][0]) dfs1(son[x][0]),siz[x]+=siz[son[x][0]];
if (son[x][1]) dfs1(son[x][1]),siz[x]+=siz[son[x][1]];
if (siz[son[x][0]]<siz[son[x][1]]) swap(son[x][0],son[x][1]);
if (son[x][0]) foot[x]=foot[son[x][0]];
}
inline void dfs2(int x,int y){
rr int now=foot[x],d=Ask(now,y);
while (dep[now]>(dep[foot[x]]+dep[y]-d)/2) now=fat[now];
if (son[now][1]) dfs2(son[now][1],y);
else{
fat[y]=now;
if (son[now][0]) son[now][1]=y;
else son[now][0]=y;
}
}
signed main(){
n=iut();
for (rr int i=2;i<=n;++i) dep[i]=Ask(1,i),rk[i]=i;
sort(rk+2,rk+1+n,cmp),fat[rk[2]]=1,son[1][0]=rk[2];
for (rr int i=3;i<=n;++i) dfs1(1),dfs2(1,rk[i]);
putchar(33);
for (rr int i=2;i<=n;++i) putchar(32),print(fat[i]);
putchar(10),fflush(stdout);
return 0;
}

#轻重链剖分,交互#LOJ 6669 Nauuo and Binary Tree的更多相关文章

  1. LOJ #6669 Nauuo and Binary Tree (交互题、树链剖分)

    题目链接 https://loj.ac/problem/6669 题解 Orz yyf太神了,出这种又有意思又有意义的好题造福人类-- 首先\(n\)次询问求出所有节点的深度. 考虑按深度扩展(BFS ...

  2. 树链剖分 (求LCA,第K祖先,轻重链剖分、长链剖分)

      2020/4/30   15:55 树链剖分是一种十分实用的树的方法,用来处理LCA等祖先问题,以及对一棵树上的节点进行批量修改.权值和查询等有奇效. So, what is 树链剖分? 可以简单 ...

  3. 洛谷 - P2146 - 软件包管理器 - 重链剖分

    https://www.luogu.org/problem/P2146 继续重链剖分. 这里好像很好懂,每次安装软件就区间改值赋值整个路径是1,然后比较前后的sum值变化就可以了.事实上后一次的sum ...

  4. luogu P3384 【模板】重链剖分

    参考https://www.cnblogs.com/wushengyang/p/10808505.html,感谢 #include<iostream> #include<algori ...

  5. codeforces gym 101611C 重链剖分构造

    给一棵树 要求在一个20*1e6的矩阵上放下这棵树,每个点的坐标都是整数且所有边都不相叉 题解 按照重链遍历,先给轻儿子坐标,然后沿着重儿子向下走即可 #include <bits/stdc++ ...

  6. 【hihocoder1167】高等理论计算机科学 (重链剖分 +树状数组)

    Descroption 原题链接给你一棵\(~n~\)个点的树和\(~m~\)条链,求两两相交的链有多少对,两条链相交当且仅当有至少一个公共点.\(~1 \leq n, m \leq 10 ^ 5~\ ...

  7. 洛谷 - P4114 - Qtree1 - 重链剖分

    https://www.luogu.org/problem/P4114 维护边权的话,用深度大的点表示这条边(可以遍历一边边询问两端深度,这样不需要修改dfs1,也可以在dfs1的时候向下走的同时把边 ...

  8. SCUT - 297 - 狂符「幻视调律(Visionary Tuning)」 - 重链剖分

    https://scut.online/p/297 一般的树剖是关于点权的,但是突发奇想好像边权也是一样的.做一些小改动. #include<bits/stdc++.h> #define ...

  9. 树链剖分【p4114】Qtree-Query on a tree I

    Description 给定一棵n个节点的树,有两个操作: CHANGE i ti 把第i条边的边权变成ti QUERY a b 输出从a到b的路径中最大的边权,当a=b的时候,输出0 Input 第 ...

  10. Query on a tree——树链剖分整理

    树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...

随机推荐

  1. 【Android 逆向】【攻防世界】easyjni

    1. apk 安装到手机,提示需要输入flag 2. jadx打开apk public class MainActivity extends c { static { System.loadLibra ...

  2. 前端树形Tree数据结构使用-🤸🏻‍♂️各种姿势总结

    01.树形结构数据 前端开发中会经常用到树形结构数据,如多级菜单.商品的多级分类等.数据库的设计和存储都是扁平结构,就会用到各种Tree树结构的转换操作,本文就尝试全面总结一下. 如下示例数据,关键字 ...

  3. 项目打包setup.py(setuptools)

    参考 https://www.cnblogs.com/dan-baishucaizi/p/13564333.html https://www.cnblogs.com/dan-baishucaizi/p ...

  4. RabbitMQ和RPC

    消息队列 消息队列中间件 (Message Queue Middleware,简称 MQ) 是指利用高效可靠的消息传递机制进行与平台无关的数据交流,它可以在分布式环境下扩展进程间的数据通信,并基于数据 ...

  5. jvm调优监控工具jps、jstack、jmap、jhat、jstat使用详解

    目录 前言 jps(Java Virtual Machine Process Status Tool) jstack jmap(Memory Map)和jhat(Java Heap Analysis ...

  6. 【Azure 环境】微软云上主机,服务的安全更新疑问

    [问题一]微软云上的虚拟机,不论是Windows系统or Linux 系统,系统的安全补丁是由微软云平台   打上补丁进行修复,还是使用虚拟机的用户手动更新修复呢? [答]这些补丁不会由平台来直接操作 ...

  7. 【Azure 应用服务】当在Azure App Service的门户上 Log Stream 日志无输出,需要如何操作让其输出Application Logs呢?

    问题描述 在Azure App Service的门户上 Log Stream 日志无输出,需要如何操作让其输出Application Logs呢? 如下图所示: 问题解答 请注意,上图中提示说:App ...

  8. Kotlin扩展函数与属性原理解析

    一.扩展函数 扩展函数可以方便地给现有类增加属性和方法而不改动类地代码. 二.原理 fun String.addTo(s: String): String{ return this + s } 反编译 ...

  9. Template String Converter - 字符串中加变量 自动将单引号变换 - vscode插件

    Template String Converter - 字符串中加变量 自动将单引号变换 - vscode插件

  10. k8s创建Pod的流程

    Kubernetes(k8s)中Pod的创建过程是一个涉及多个组件协作的复杂流程,下面将详细描述这个过程,确保内容的详尽性和深度. 一.用户提交创建请求 Pod的创建始于用户通过kubectl命令行工 ...