「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 ...
随机推荐
- androidstudio Cannot resolve symbol 'xxx'
Android Studio 无法识别同一个 package 里的其他类,将其显示为红色,但是 compile 没有问题.鼠标放上去后显示 “Cannot resolve symbol XXX”,重启 ...
- oracle 用户账户被锁处理
一.以管理员身份登录 SQL> conn sys/sys as sysdba; (分号是必须的但是我是以system登录的所在这不应该写conn sys/sys as sysdba应该写conn ...
- Objective-c写冒泡排序
做面试题遇到用obj-c写冒泡排序,随便写了个 - (NSMutableArray *)sorted:(NSMutableArray *)array { int len = [array count] ...
- Jupyter Notebook 基本使用
Jupyter 官网 IPython Interactive Computing IPython Notebook使用浏览器作为界面,向后台的IPython服务器发送请求,并显示结果.在浏览器的界面中 ...
- [转]图解eclipse 查看原始类出现The jar file rt.jar has no source attachment
原文:http://blog.csdn.net/u011514810/article/details/53196371 ---------------------------------------- ...
- 新浪微博发送消息和授权机制原理(WeiboSDK)
1.首先是在微博发送消息,对于刚開始做weibo发送消息的刚開始学习的人会有一个误区,那就是会觉得须要授权后才干够发送消息.事实上发送消息仅仅须要几行代码就能够实现了,很easy,不须要先授权再发送消 ...
- stl 之set图解
使用set或multiset之前,必须增加头文件<set> Set.multiset都是集合类,区别在与set中不同意有反复元素,multiset中同意有反复元素. sets和multis ...
- android KE or NE分析
使用arm-eabi-addr2line工具跟踪Android调用堆栈 在通常的C/C++代码中,可以通过响应对内存操作不当引起的Segmentation Fault错误即信号SIGSEGV(11)做 ...
- gbk转utf-8 iconv 编码转换
linux以下有时候 字符须要进行编码转换(爬虫将gbk转为utf-8编码...).一般能够选择iconv函数. 终端以下 输入 man 3 iconv 得到 iconv函数的用法. 个人看习惯了 ...
- 使用mongostat监视mongodb
1, 监视一个mongod mongostat 10.80.1.1:27018 1,监视replica set mongostat --host rs0/10.80.1.1:27018,10.80.1 ...