「vijos」lxhgww的奇思妙想(长链剖分)
长链剖分的板子(又是乱搞优化暴力)
对于每一个点,我们定义它深度最深的子节点为它的重儿子(为什么不叫长儿子……),他们之间的连边为重边
然后长链剖分有几个性质
1.总链长为$O(n)$
2.一个节点的$k$级祖先的子树深度必定大于等于当前节点的子树深度
以上两点稍微yy一下就能发现是对的
然后回到这道题。我们设$len[u]$为这一条长链的长度,对于每一个长链的顶点,我们维护它的1到$len[u]$级儿子以及1到$len[u]$级祖先
同时预处理找祖先的倍增数组,并预处理出1到$n$的每一个数字的二进制最高位即$highbit$
那么对于每一个询问$(u,k)$,我们设$r=highbit(k)$,那么我们用预处理的倍增数组让$u$跳到它的$r$级祖先$v$处
因为$k-r<r$,那么$v$的长链的长度$\geq r>k-r$,那么$v$所在的长链预处理的表一定已经包含了$u$的$k$级祖先
时间复杂度为$O(nlogn+m)$,预处理$O(nlogn)$,每一次回答$O(1)$
//minamoto
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char sr[<<],z[];int C=-,Z;
inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
void print(int x){
if(C><<)Ot();if(x<)sr[++C]=,x=-x;
while(z[++Z]=x%+,x/=);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=3e5+;
int head[N],Next[N<<],ver[N<<],tot;
inline void add(int u,int v){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
}
int n,md[N],dep[N],fa[N][],son[N],top[N],len[N],B[N];
vector<int> U[N],D[N];
void dfs(int u,int f){
md[u]=dep[u]=dep[f]+,fa[u][]=f;
for(int i=;i<;++i)
if(fa[u][i-]) fa[u][i]=fa[fa[u][i-]][i-];
else break;
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v!=f){
dfs(v,u);
if(md[son[u]]<md[v]) son[u]=v,md[u]=md[v];
}
}
}
void dfs2(int u,int t){
top[u]=t,len[u]=md[u]-dep[t]+;
if(son[u]){
dfs2(son[u],t);
for(int i=head[u];i;i=Next[i])
if(!top[ver[i]]) dfs2(ver[i],ver[i]);
}
}
void init(){
int now=;
for(int i=;i<=n;++i){
if(!(i&(<<now))) ++now;
B[i]=now;
}
for(int i=;i<=n;++i)
if(i==top[i]){
for(int j=,u=i;j<=len[i]&&u;++j) u=fa[u][],U[i].push_back(u);
for(int j=,u=i;j<=len[i]&&u;++j) u=son[u],D[i].push_back(u);
}
}
int query(int u,int k){
if(k>dep[u]) return ;if(k==) return u;
u=fa[u][B[k]],k^=<<B[k];
if(k==) return u;
if(dep[u]-dep[top[u]]==k) return top[u];
if(dep[u]-dep[top[u]]<k) return U[top[u]][k-dep[u]+dep[top[u]]-];
else return D[top[u]][dep[u]-dep[top[u]]-k-];
}
int main(){
// freopen("testdata.in","r",stdin);
n=read();
for(int i=;i<n;++i){
int u=read(),v=read();
add(u,v),add(v,u);
}
dfs(,),dfs2(,),init();
int lastans=,q=read();
while(q--){
int u=read()^lastans,v=read()^lastans;
printf("%d\n",lastans=query(u,v));
}
return Ot(),;
}
「vijos」lxhgww的奇思妙想(长链剖分)的更多相关文章
- 「vijos-bashu」lxhgww的奇思妙想(长链剖分)
倍增离线,预处理出爹和孙子们.查询\(O(1)\) #include <cstdio> #include <cstring> #include <numeric> ...
- [vijos]lxhgww的奇思妙想(长链剖分)
题意 题目链接 Sol 长链剖分 又是一个用各种花式技巧优化的暴力 它的主要思想是:对于每个节点,把深度最深的子节点当做重儿子,它们之间的边当做重边 这样就会有一些非常好的轻质 所有链长总和是\(O( ...
- lxhgww的奇思妙想 长链剖分板子
https://vijos.org/d/Bashu_OIers/p/5a79a3e1d3d8a103be7e2b81 求k级祖先,预处理nlogn,查询o1 //#pragma GCC optimiz ...
- 「HAOI2015」「LuoguP3178」树上操作(树链剖分
题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增 ...
- 「LuoguP3384」【模板】树链剖分
题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...
- 【Vijos】lxhgww的奇思妙想(长链剖分)
题面 给定一棵树,每次询问一个点的\(k\)次祖先,强制在线. Vijos 题解 长链剖分. 链接暂时咕咕咕了. 现在可以戳链接看题解了 #include<iostream> #inclu ...
- Vijos.lxhgww的奇思妙想(k级祖先 长链剖分)
题目链接 https://blog.bill.moe/long-chain-subdivision-notes/ http://www.cnblogs.com/zzqsblog/p/6700133.h ...
- 2019.01.06 vijos lxhgww的奇思妙想(长链剖分)
传送门 长链剖分模板题. 题意简述:允许O(nlogn)O(nlog_n)O(nlogn)预处理,让你支持O(1)O(1)O(1)查找任意一个点的kkk级祖先. 思路:因为要O(1)O(1)O(1) ...
- 【COGS2652】秘术「天文密葬法」(长链剖分,分数规划)
[COGS2652]秘术「天文密葬法」(长链剖分,分数规划) 题面 Cogs 上面废话真多,建议直接拉到最下面看一句话题意吧: 给个树,第i个点有两个权值ai和bi,现在求一条长度为m的路径,使得Σa ...
随机推荐
- HDU 1669 二分图多重匹配+二分
Jamie's Contact Groups Time Limit: 15000/7000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/ ...
- Nginx: 解决connect() to xxxx failed (13: Permission denied) while connecting to upstream的问题
一句话:setsebool httpd_can_network_connect true
- 【APUE】进程间通信之管道
管道是UNIX系统IPC最古老形式,并且所有UNIX系统都提供此种通信机制.管道由下面两种局限性: 1)历史上,它们是半双工的(即数据只能在一个方向上流动) 2)它们只能在具有公共祖先的进程之间使用. ...
- HNU 12834 Thread Tree
递归输出即可了 #include<bits/stdc++.h> using namespace std; struct tree{ int dot; string s; } ...
- ElasticSearch(5.5.2)在java中的使用
ElasticSearch(5.5.2)在java中的使用 https://blog.csdn.net/didiaodeabing/article/details/79310710 pom.xml: ...
- Null value was assigned to a property of primitive type setter of原因及解决
出现Null value was assigned to a property of primitive type setter of错误是由于类型不匹配,将字段的属性由hibernate的int类型 ...
- Android使用am命令实现拨打电话、打开应用
前提: 在Android 通话自己主动化測试中会用到am命令去拨打电话.打开音乐播放器播放音乐等等操作. 这里总结一下am命令. Android am命令: (1)命令參数: am start -n ...
- WebApi-路由机制 Visual Studio 2015中的常用调试技巧分享
WebApi-路由机制 一.WebApi路由机制是什么? 路由机制通俗点来说:其实就是WebApi框架将用户在浏览器中输入的Url地址和路由表中的路由进行匹配,并根据最终匹配的路由去寻找并匹配相应 ...
- serverSpeed是一个android手机端到服务器间udp/tcp对比测速软件
https://github.com/eltld/serverSpeed https://github.com/c-wind/serverSpeed https://github.com/PeterK ...
- IIS7添加虚拟目录映射另一台服务器的共享文件夹
现状: 一台Windows Server2008 Web服务器 A,一台Windows Server2003 文件服务器 B,需要在A中IIS添加对B的Web访问 方法: 1.A中添加和B相同的账号, ...