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)求,因此需要用到长链剖分的一些性质。
所谓长链剖分是类比重链剖分的一种划分树的方式,我们考虑将整棵树用若干条极长链拼接起来就是长链剖分。
那么它有如下几个几个性质:
- 所有长链的长度之和为O(n)O(n)O(n)
- 一个节点的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的奇思妙想(长链剖分)的更多相关文章
- [vijos]lxhgww的奇思妙想(长链剖分)
题意 题目链接 Sol 长链剖分 又是一个用各种花式技巧优化的暴力 它的主要思想是:对于每个节点,把深度最深的子节点当做重儿子,它们之间的边当做重边 这样就会有一些非常好的轻质 所有链长总和是\(O( ...
- lxhgww的奇思妙想 长链剖分板子
https://vijos.org/d/Bashu_OIers/p/5a79a3e1d3d8a103be7e2b81 求k级祖先,预处理nlogn,查询o1 //#pragma GCC optimiz ...
- 「vijos-bashu」lxhgww的奇思妙想(长链剖分)
倍增离线,预处理出爹和孙子们.查询\(O(1)\) #include <cstdio> #include <cstring> #include <numeric> ...
- 【LOJ】#3014. 「JOI 2019 Final」独特的城市(长链剖分)
LOJ#3014. 「JOI 2019 Final」独特的城市(长链剖分) 显然我们画一条直径,容易发现被统计的只可能是直径某个距离较远的端点到这个点的路径上的值 用一个栈统计可以被统计的点,然后我们 ...
- 219.01.19 bzoj3252: 攻略(长链剖分+贪心)
传送门 长链剖分好题. 题意:给一棵带点权的树,可以从根节点到任一叶节点走kkk次,走过的点只能计算一次,问kkk次走过的点点权值和最大值. 思路: 考虑将整棵树带权长链剖分,这样链与链之间是不会重复 ...
- 2019.01.20 bzoj2238: Mst(kruskal+树链剖分)
传送门 树链剖分菜题. 题意简述:给一个无向图,边有边权,每次询问删一条边(对后面的询问无影响)之后的最小生成树. 思路: 先跑一次kruskalkruskalkruskal并把跑出来的最小生成树给链 ...
- 2019.01.20 bzoj3999: [TJOI2015]旅游(树链剖分)
传送门 树链剖分菜题. 题意不清差评. 题意简述(保证清晰):给一棵带权的树,每次从aaa走到bbb,在走过的路径上任意找两个点,求后访问的点与先访问的点点权差的最大值. 思路: 考虑暴力:维护路径的 ...
- 2019.01.13 bzoj4538: [Hnoi2016]网络(树链剖分)
传送门 树链剖分一眼题. 题意简述: 给定一棵树,有三种操作: 加入一条路径 删除一条已加入的路径 询问不过一个点x的路径的最大值. 思路: 直接树链剖分维护答案. 因为询问的事不过点xxx的最大值, ...
- 【Vijos】lxhgww的奇思妙想(长链剖分)
题面 给定一棵树,每次询问一个点的\(k\)次祖先,强制在线. Vijos 题解 长链剖分. 链接暂时咕咕咕了. 现在可以戳链接看题解了 #include<iostream> #inclu ...
随机推荐
- [leetcode]161. One Edit Distance编辑步数为一
Given two strings s and t, determine if they are both one edit distance apart. Note: There are 3 pos ...
- java 爬虫
由于项目需求,综合了几种考虑方案,准备使用java 爬虫进行数据的获取,不用自己去费劲的想逻辑的实现 使用java爬虫之前,我们必须要掌握的知识: 1. 对前端HTML的元素有一定的认识 2. 使用h ...
- 我的第一个博客——Fragment遇到的问题
最近项目中使用fragment时遇到了一些问题: 1.fragment的刷新问题. 解决:我的情况是有多个fragment时,只需要刷新其中几个界面.之前我在网上看到的一些方法.如下: 首先在Adap ...
- 安装后没有IP
修改 /etc/sysconfig/network-scripts/ifcfg-eth0 改为yes
- 【C++】:STL迭代器使用---[容器::iterator iter;]
参考文章:http://blog.csdn.net/qq_23100787/article/details/51388163 迭代器这种东西,就是为了使访问简单!! 容器::iterator iter ...
- (轉)JSON.stringify 语法实例讲解
作用:这个函数的作用主要是为了系列化对象的. 可能有些人对系列化这个词过敏,我的理解很简单.就是说把原来是对象的类型转换成字符串类型(或者更确切的说是json类型的).就这么简单.打个比方说,你有一个 ...
- UVALive - 3266 (贪心) 田忌赛马
耳熟能详的故事,田忌赛马,第一行给出田忌的马的速度,第二行是齐王的马的速度,田忌赢一场得200,输一场失去200,平局不得也不失,问最后田忌最多能得多少钱? 都知道在故事里,田忌用下等马对上等马,中等 ...
- 错误:在非结构或联合中请求成员‘next’
#include <stdio.h> #include <stdlib.h> #define ElemType int #define Status int #define O ...
- Intellij IDEA 快捷键整理-鬼畜版(全键盘开发指南)
一 .何为鬼畜? 鬼畜一词在ACG爱好者中也代指通过影片(或音讯)剪辑,用频率极高的重复画面(或声音)组合而成的一段节奏配合音画同步率极高的一类影片,而这类鬼畜影片多见于NICONICO.AcFun和 ...
- MySQL学习笔记-MySQL体系结构总览
MySQL体系结构总览 不管是用哪种数据库,了解数据库的体系结构都是极为重要的.MySQL体系结构主要由数据库和数据库实例构成. 数据库:物理操作系统文件或者其它文件的集合,在mysql中,数据库文件 ...