传送门

长链剖分模板题。

题意简述:允许O(nlogn)O(nlog_n)O(nlogn​)预处理,让你支持O(1)O(1)O(1)查找任意一个点的kkk级祖先。


思路:因为要O(1)O(1)O(1)求,因此需要用到长链剖分的一些性质。

所谓长链剖分是类比重链剖分的一种划分树的方式,我们考虑将整棵树用若干条极长链拼接起来就是长链剖分。

那么它有如下几个几个性质:

  1. 所有长链的长度之和为O(n)O(n)O(n)
  2. 一个节点的kkk级祖先所在的长链的长度至少为kkk 可以根据长链剖分的定义想

    然后这题就可以做出来了。

具体实现:

对于长链的每一个上顶点ppp,我们设其引导的长链长度为lenlenlen,我们预处理出ppp的000 ~ lenlenlen级祖先和000~lenlenlen级的长儿子(即它引导的这条链),然后用O(nlogn)O(nlogn)O(nlogn)的时空预处理出一个祖先的倍增数组以及预处理一个数组highbithighbithighbit存每个数对应的二进制位最高位是第几位。

考虑一个查询(p,r)(p,r)(p,r)即查询ppp点的rrr级祖先。

我们先通过倍增数组将ppp跳到其2highbitr2^{highbit_{r}}2highbitr​级祖先yyy,然后剩下的r−highbitrr-highbit_rr−highbitr​是小于highbitrhighbit_rhighbitr​的,有性质2可以知道这个祖先一定存在yyy在的链顶上,然后就可以查出来了。

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
const int N=3e5+5;
int top[N],st[N][21],Log[N],n,m,dep[N],hson[N],mdep[N],highbit[N];
vector<int>e[N],son[N],anc[N];
inline void init(){
	Log[1]=0,highbit[1]=0;
	for(ri i=2;i<=n;++i)Log[i]=Log[i>>1]+1,highbit[i]=highbit[i-1]+(i>>(highbit[i-1]+1)&1);
	for(ri i=1;i<=n;++i){
		if(top[i]==i){
			int up=mdep[i]-dep[i];
			for(ri v=i,j=0;j<=up;++j)son[i].push_back(v),v=hson[v];
			for(ri v=i,j=0;j<=up;++j)anc[i].push_back(v),v=st[v][0];
		}
	}
	for(ri j=1;j<=20;++j)for(ri i=1;i<=n;++i)st[i][j]=st[st[i][j-1]][j-1];
}
void dfs1(int p){
	for(ri v,i=0;i<e[p].size();++i){
		if((v=e[p][i])==st[p][0])continue;
		st[v][0]=p,mdep[v]=dep[v]=dep[p]+1,dfs1(v),mdep[p]=max(mdep[v],mdep[p]);
		if(mdep[v]>mdep[hson[p]])hson[p]=v;
	}
}
void dfs2(int p,int tp){
	top[p]=tp;
	if(!hson[p])return;
	dfs2(hson[p],tp);
	for(ri i=0,v;i<e[p].size();++i){
		v=e[p][i];
		if(v==st[p][0]||v==hson[p])continue;
		dfs2(v,v);
	}
}
inline int query(int x,int k){
	if(k>dep[x])return 0;
	if(!k)return x;
	int y=st[x][highbit[k]];
	k-=1<<highbit[k];
	if(!k)return y;
	if(dep[y]-dep[top[y]]<=k)return anc[top[y]][k-dep[y]+dep[top[y]]];
	return son[top[y]][dep[y]-dep[top[y]]-k];
}
int main(){
	n=read();
	for(ri i=1,u,v;i<n;++i)u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
	dfs1(1),dfs2(1,1),init();
	for(ri tt=read(),lastans=0,x,k;tt;--tt)x=read()^lastans,k=read()^lastans,cout<<(lastans=query(x,k))<<'\n';
	return 0;
}

2019.01.06 vijos lxhgww的奇思妙想(长链剖分)的更多相关文章

  1. [vijos]lxhgww的奇思妙想(长链剖分)

    题意 题目链接 Sol 长链剖分 又是一个用各种花式技巧优化的暴力 它的主要思想是:对于每个节点,把深度最深的子节点当做重儿子,它们之间的边当做重边 这样就会有一些非常好的轻质 所有链长总和是\(O( ...

  2. lxhgww的奇思妙想 长链剖分板子

    https://vijos.org/d/Bashu_OIers/p/5a79a3e1d3d8a103be7e2b81 求k级祖先,预处理nlogn,查询o1 //#pragma GCC optimiz ...

  3. 「vijos-bashu」lxhgww的奇思妙想(长链剖分)

    倍增离线,预处理出爹和孙子们.查询\(O(1)\) #include <cstdio> #include <cstring> #include <numeric> ...

  4. 【LOJ】#3014. 「JOI 2019 Final」独特的城市(长链剖分)

    LOJ#3014. 「JOI 2019 Final」独特的城市(长链剖分) 显然我们画一条直径,容易发现被统计的只可能是直径某个距离较远的端点到这个点的路径上的值 用一个栈统计可以被统计的点,然后我们 ...

  5. 219.01.19 bzoj3252: 攻略(长链剖分+贪心)

    传送门 长链剖分好题. 题意:给一棵带点权的树,可以从根节点到任一叶节点走kkk次,走过的点只能计算一次,问kkk次走过的点点权值和最大值. 思路: 考虑将整棵树带权长链剖分,这样链与链之间是不会重复 ...

  6. 2019.01.20 bzoj2238: Mst(kruskal+树链剖分)

    传送门 树链剖分菜题. 题意简述:给一个无向图,边有边权,每次询问删一条边(对后面的询问无影响)之后的最小生成树. 思路: 先跑一次kruskalkruskalkruskal并把跑出来的最小生成树给链 ...

  7. 2019.01.20 bzoj3999: [TJOI2015]旅游(树链剖分)

    传送门 树链剖分菜题. 题意不清差评. 题意简述(保证清晰):给一棵带权的树,每次从aaa走到bbb,在走过的路径上任意找两个点,求后访问的点与先访问的点点权差的最大值. 思路: 考虑暴力:维护路径的 ...

  8. 2019.01.13 bzoj4538: [Hnoi2016]网络(树链剖分)

    传送门 树链剖分一眼题. 题意简述: 给定一棵树,有三种操作: 加入一条路径 删除一条已加入的路径 询问不过一个点x的路径的最大值. 思路: 直接树链剖分维护答案. 因为询问的事不过点xxx的最大值, ...

  9. 【Vijos】lxhgww的奇思妙想(长链剖分)

    题面 给定一棵树,每次询问一个点的\(k\)次祖先,强制在线. Vijos 题解 长链剖分. 链接暂时咕咕咕了. 现在可以戳链接看题解了 #include<iostream> #inclu ...

随机推荐

  1. 15. 3Sum (重新分配数组大小)

    Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all un ...

  2. javascript实现留言功能

    原理: 1.用户在留言框输入留言 2.利用textarea的value属性获取到用户输入的留言 3.动态创建一个li 4.将获取的留言打包成html存到li中 5.根据需要添加删除留言.统计留言数量等 ...

  3. jquery 事件委托(利用冒泡)

    将事件绑定在父元素上,格式$(父元素).on("事件名称","子元素选择器",function(方法体){}) <!DOCTYPE html> &l ...

  4. redis-storage介绍[转]

    背景: 当时我们正在做一个游戏项目,游戏项目相比于web项目,更追求的是单机的性能,而我们对单个请求的处理时间有着bt级的需求(一个完整的api请求控制在10ms以内).当时我们的数据层用的是ttse ...

  5. Linux下 MYSQL 主从复制、同步

    mysql从3.23.15版本以后提供数据库复制功能.利用该功能可以实现两个数据库同步,主从模式(A->B),互相备份模式(A<=>B)的功能. 主从模式(A->B)的配置过程 ...

  6. C# Request.RawUrl与Request.Url的区别

    RawUrl——不包含域名及端口的地址 Url——包含域名,最全

  7. Java运算符号,对象赋值,别名

    生活发生的一切,才会促使着我继续前行,今天继续更新哦,看书中的代码练习. 例子1  引入net.mindview.util.Print.* ,方便打印结果. package com.date0529; ...

  8. python学习笔记Day3

    set有点:1.访问速度快 2.天生解决了重复问题 tuple与set区别: 元组可重复,set不可重复创捷集合1 >>> s1.add('alex')>>> pr ...

  9. 5B - 一只小蜜蜂...

    有一只经过训练的蜜蜂只能爬向右侧相邻的蜂房,不能反向爬行.请编程计算蜜蜂从蜂房a爬到蜂房b的可能路线数. 其中,蜂房的结构如下所示.  Input 输入数据的第一行是一个整数N,表示测试实例的个数,然 ...

  10. DOM心得

    一.自定义属性值两种方法的注意事项 1.用元素节点.属性(元素节点[属性])绑定的属性值不会出现在标签上. 2.用get/set/removeAttribut(,)等绑定的属性会出现在标签上.且两种方 ...