#轻重链剖分,交互#LOJ 6669 Nauuo and Binary Tree
题目
有一棵大小为\(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的更多相关文章
- LOJ #6669 Nauuo and Binary Tree (交互题、树链剖分)
题目链接 https://loj.ac/problem/6669 题解 Orz yyf太神了,出这种又有意思又有意义的好题造福人类-- 首先\(n\)次询问求出所有节点的深度. 考虑按深度扩展(BFS ...
- 树链剖分 (求LCA,第K祖先,轻重链剖分、长链剖分)
2020/4/30 15:55 树链剖分是一种十分实用的树的方法,用来处理LCA等祖先问题,以及对一棵树上的节点进行批量修改.权值和查询等有奇效. So, what is 树链剖分? 可以简单 ...
- 洛谷 - P2146 - 软件包管理器 - 重链剖分
https://www.luogu.org/problem/P2146 继续重链剖分. 这里好像很好懂,每次安装软件就区间改值赋值整个路径是1,然后比较前后的sum值变化就可以了.事实上后一次的sum ...
- luogu P3384 【模板】重链剖分
参考https://www.cnblogs.com/wushengyang/p/10808505.html,感谢 #include<iostream> #include<algori ...
- codeforces gym 101611C 重链剖分构造
给一棵树 要求在一个20*1e6的矩阵上放下这棵树,每个点的坐标都是整数且所有边都不相叉 题解 按照重链遍历,先给轻儿子坐标,然后沿着重儿子向下走即可 #include <bits/stdc++ ...
- 【hihocoder1167】高等理论计算机科学 (重链剖分 +树状数组)
Descroption 原题链接给你一棵\(~n~\)个点的树和\(~m~\)条链,求两两相交的链有多少对,两条链相交当且仅当有至少一个公共点.\(~1 \leq n, m \leq 10 ^ 5~\ ...
- 洛谷 - P4114 - Qtree1 - 重链剖分
https://www.luogu.org/problem/P4114 维护边权的话,用深度大的点表示这条边(可以遍历一边边询问两端深度,这样不需要修改dfs1,也可以在dfs1的时候向下走的同时把边 ...
- SCUT - 297 - 狂符「幻视调律(Visionary Tuning)」 - 重链剖分
https://scut.online/p/297 一般的树剖是关于点权的,但是突发奇想好像边权也是一样的.做一些小改动. #include<bits/stdc++.h> #define ...
- 树链剖分【p4114】Qtree-Query on a tree I
Description 给定一棵n个节点的树,有两个操作: CHANGE i ti 把第i条边的边权变成ti QUERY a b 输出从a到b的路径中最大的边权,当a=b的时候,输出0 Input 第 ...
- Query on a tree——树链剖分整理
树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...
随机推荐
- [BUUCTF][Web][极客大挑战 2019]Havefun 1
打开靶机的URL,看到一个页面 右键查看源代码,看到有用信息 <html> ... <!-- $cat=$_GET['cat']; echo $cat; if($cat=='dog' ...
- 2021-10-11 vue的第三方组件二次封装
原理 v-bind="$attrs"继承所有属性和props. v-on="$listeners"继承所有的方法. <template> <d ...
- isort包
记录 为什么会使用到这个包,原因是之前在本地开发的时候,导包的时候可能由于不规范,其实你自己看着挺规范的,但是呢后续组长进行打包的时候,代码出现了不规范的情况,导致打包失败.原因就是导包不规范造成的. ...
- python如何多版本共存
1. 先正常安装多个python版本,比如我电脑里面是安装的3.10以及3.12 2. 安装的时候建议不要选择系统盘,可以用两个目录安装,例如: d:\py310\... d:\py312\... 3 ...
- 【应用服务 App Service】 App Service Rewrite 实例 -- 限制站点的访问
问题描述 在Azure App Service中,当需要限制某些特殊的情况对其进行访问时候,可以通过IP限制,逻辑代码判断,或者Rewrite规则.通过IP限制则需要知道客户端访问的IP,而通过逻辑代 ...
- 【Azure 事件中心】Flink消费Event Hub中事件, 使用Azure默认示例代码,始终获取新产生的事件,如何消费旧事件呢?
问题描述 根据Azure Event Hub示例文档,[将 Apache Flink 与适用于 Apache Kafka 的 Azure 事件中心配合使用],配置好 consumer.config 文 ...
- 【Azure Developer】解答《美丽的数学》一书中P120页的一道谜题:寻找第四个阶乘和数
一道谜题 在观看<美丽的数学>一书中,在120页中有一道谜题: 数字145被称为一个阶乘和数, 因为它具有以下有趣的属性,如果我们将它的各位数字的阶乘相加,会得到该数字本身 1! +4! ...
- C++11新特性的一些用法举例②
/** C++11 * 默认成员函数 原来C++类中,有6个默认成员函数: 构造函数 析构函数 拷贝构造函数 拷贝赋值重载 取地址重载 const 取地址重载 最后重要的是前4个,后两个用处不大.默认 ...
- C++ //类模板对象做函数参数 //三种方式 //1.指定传入的类型 --直接显示对象的数据类型 //2.参数模板化 --将对象中的参数变为模板进行传递 //3.整个类模板化 --将这个对象类型 模板化进行传递
1 //类模板对象做函数参数 2 //三种方式 3 //1.指定传入的类型 --直接显示对象的数据类型 4 //2.参数模板化 --将对象中的参数变为模板进行传递 5 //3.整个类模板化 --将这个 ...
- liunx 安装 python 虚拟环境, 各种方法,
liunx 安装 python 虚拟环境,主要是要解决工作中需要用到python3.6,但是系统的2.7又不能动,安装系统组件时避免造成冲突.低版本的python安装django uwsgi 等都用 ...