Vijos lxhgww的奇思妙想--求K级祖先
给出一棵树求K级祖先。O(N*logN+Q)
更详细的讲解见:https://www.cnblogs.com/cjyyb/p/9479258.html
/*
要求k级祖先,我们可以把k拆成"2^highbit(x)+tmp 形式
(highbit(x)为x在二进制位下的最高位),然后用倍增的方法把highbit(x)的部分跳了
剩下tmp的同样可以预处理掉,这样预处理就是O(n*logn)的效率,
所以对于每个询问就是O(1)回答,这样的效率就是O(n*logn+q)。
于是就考虑用长链剖分。
讲讲具体的细节操作。
数组:
f[i][j]:i的倍增得到的祖先
d[i]:i i的最深的儿子的深度(用于处理len lenlen)
dep[i]:i的节点深度
son[i]:i的长儿子
len[i]:i为长链顶点的链长
top[i]:i所在长链的顶点
hb[i]:i的highbit highbithighbit值
twi[i]:2^i
预处理:
对于highbit(x) 选择你喜欢的方法做。
对于tmp,用两个动态数组维护,存每条长链的顶点的向上len
向下len的祖先和儿子
(对于每条长链,存链中的节点显然无意义,因为你可以在询问时先跳到top)。
深搜:
一共dfs两遍
dfs1:预处理一些关于树的常规信息,如深度、长儿子
dfs2:处理链长和长链顶点
原文链接:https://blog.csdn.net/hzq_oi/article/details/88595343
*/
#include<bits/stdc++.h>
#define N 300005
using namespace std;
inline int rd()
{
int data=0,w=1;static char ch=0;
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(isdigit(ch))data=(data<<1)+(data<<3)+ch-'0',ch=getchar();
return data*w;
}
int first[N],cnt;
struct node
{int v,nxt;}
e[N<<1];
inline void add(int u,int v)
{
e[++cnt].v=v;
e[cnt].nxt=first[u];
first[u]=cnt;
}
int n,m,ans;
int f[N][20],d[N],dep[N],len[N],top[N],son[N],hb[N],twi[30];
void dfs1(int u,int fa) //根的深度为1
{
d[u]=dep[u]=dep[fa]+1;
f[u][0]=fa;
for(int register i=1;i<=19;i++)
f[u][i]=f[f[u][i-1]][i-1];
for(int register i=first[u];i;i=e[i].nxt)
{
int register v=e[i].v;
if(v==fa)continue;
dfs1(v,u);
if(d[u]<d[v]) //找出重儿子
{
d[u]=d[v];
son[u]=v;
}
}
}
void dfs2(int u,int fa)
{
len[u]=d[u]-dep[top[u]]+1;
if(!son[u])return;
top[son[u]]=top[u];
dfs2(son[u],u);
for(int register i=first[u];i;i=e[i].nxt)
if(e[i].v!=son[u]&&e[i].v!=fa)
top[e[i].v]=e[i].v,dfs2(e[i].v,u);
}
vector<int>up[N],down[N];
inline int query(int x,int k)//求k级祖先
{
if(k>=dep[x])return 0;
if(!k)return x;
x=f[x][hb[k]];//hb[k]代表k这个数字的最高位是2的多少次方
k^=twi[hb[k]];
if(!k)return x;
int register tmp=dep[x]-dep[top[x]];
if(tmp==k)
return top[x];
else
if(tmp<k)return
up[top[x]][k-tmp-1];
//x在某条轻链上,跳到top点后,还不够,不要向上跳
else
return down[top[x]][tmp-k-1];
//x在重链上,跳到top点后,跳过头了,所以还要向下移动下
}
int main()
{
n=rd();
for(int register i=1;i<n;i++)
{int register x=rd(),y=rd();add(x,y);add(y,x);}
dfs1(1,0);
top[1]=1;
dfs2(1,0); for(int i=1;i<=n;i++)
{
if(i!=top[i]) continue;
//找出每条重链的顶点
int register tmp=0,prv=i;
while(tmp<len[i]&&prv)
{
prv=f[prv][0],up[i].push_back(prv),tmp++;
}
tmp=0;prv=i;
while(tmp<len[i])
{
prv=son[prv],down[i].push_back(prv),tmp++;
//向下跳,跳到它的重儿子 }
}
twi[0]=1;
for(int register i=1;i<=20;i++)
twi[i]=twi[i-1]<<1;
for(int register i=1;i<=n;i++)
for(int register j=20;j>=0;j--)
if(twi[j]&i)
{
hb[i]=j;
//对于数字i来说,它转成2进制后最高位是2^j
//例如7的最高位是2^2,8的是2^3
break;
}
m=rd();
while(m--)
{
int register x=rd(),k=rd();
x^=ans;
k^=ans;
ans=query(x,k);
printf("%d\n",ans);
}
return 0;
}
Vijos lxhgww的奇思妙想--求K级祖先的更多相关文章
- [vijos]lxhgww的奇思妙想(长链剖分)
题意 题目链接 Sol 长链剖分 又是一个用各种花式技巧优化的暴力 它的主要思想是:对于每个节点,把深度最深的子节点当做重儿子,它们之间的边当做重边 这样就会有一些非常好的轻质 所有链长总和是\(O( ...
- 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) ...
- Vijos.lxhgww的奇思妙想(k级祖先 长链剖分)
题目链接 https://blog.bill.moe/long-chain-subdivision-notes/ http://www.cnblogs.com/zzqsblog/p/6700133.h ...
- 【Vijos】lxhgww的奇思妙想
题面 题解 求$k$级祖先孙子 为什么要用长链剖分啊??? 倍增并没有慢多少... 其实是我不会 长链剖分做这道题还是看这位巨佬的吧. 代码 #include<bits/stdc++.h> ...
- lxhgww的奇思妙想 长链剖分板子
https://vijos.org/d/Bashu_OIers/p/5a79a3e1d3d8a103be7e2b81 求k级祖先,预处理nlogn,查询o1 //#pragma GCC optimiz ...
- 「vijos」lxhgww的奇思妙想(长链剖分)
传送门 长链剖分的板子(又是乱搞优化暴力) 对于每一个点,我们定义它深度最深的子节点为它的重儿子(为什么不叫长儿子……),他们之间的连边为重边 然后长链剖分有几个性质 1.总链长为$O(n)$ 2.一 ...
- 【Vijos】lxhgww的奇思妙想(长链剖分)
题面 给定一棵树,每次询问一个点的\(k\)次祖先,强制在线. Vijos 题解 长链剖分. 链接暂时咕咕咕了. 现在可以戳链接看题解了 #include<iostream> #inclu ...
- 【LCA求最近公共祖先+vector构图】Distance Queries
Distance Queries 时间限制: 1 Sec 内存限制: 128 MB 题目描述 约翰的奶牛们拒绝跑他的马拉松,因为她们悠闲的生活不能承受他选择的长长的赛道.因此他决心找一条更合理的赛道 ...
- POJ 1986 Distance Queries (Tarjan算法求最近公共祖先)
题目链接 Description Farmer John's cows refused to run in his marathon since he chose a path much too lo ...
随机推荐
- exe远程注入线程xp
进程删除不了 某目录下txt ini config 无法修改
- c字符串函数
1. bcmp(3) 类ma似于strncmp(3) 但是比较结果不一定是两个字符的ascii码之差. 返回值:相等0,不相等非零(不一定是-1) 2.bcopy(3)类ma似于strncpy(3) ...
- 【洛谷P2447】外星千足虫
题目大意:给定一个 M 个含 N 个未知数的异或方程组,保证有解,若存在唯一解,给出至少需要几个方程才能得出唯一解,若不存在,直接输出不存在. 题解:异或方程组也满足类似初等行变换的操作,只不过所有的 ...
- 【练习】(a,b)和(b,a)是相同的,如何去除(b,a)保留(a,b)
[(0, 3), (0, 11), (1, 8), (1, 9), (1, 15), (3, 0), (8, 1), (8, 9), (8, 15), (9, 1), (9, 8), (9, 15), ...
- HIVE 必知必会
hive: 基于hadoop,数据仓库软件,用作OLAP OLAP:online analyze process 在线分析处理OLTP:online transaction process 在线事务处 ...
- Mac SIP系统完整性保护如何关闭
方法/步骤1: 打开Mac终端输入命令:csrutil status 它会显示关闭的话是disable,开启的话是enabled.默认情况下是开启的所以要关闭. 方法/步骤2: 点击桌面的apple ...
- 【NOIP2016提高A组模拟9.17】数格子
题目 分析 设表示每一行的状态,用一个4位的二进制来表示,当前这一行中的每一个位数对下一位有没有影响. 设\(f_{i,s}\)表示,做完了的i行,其状态为s,的方案数. 两个状态之间是否可以转移就留 ...
- TTTTTTTTTTT LA 4329 BIT模版
题意: 有n个打乒乓球的人,住在一排房子内,以房子的顺序从做到由,每个人都有一个不同的乒乓球等级ai.每次比赛需要三人,两人比赛和一人裁判,裁判必须居住在两个比赛者之间,且等级必须也在两个人之间.问最 ...
- navicat安装与激活
原文网址:https://www.jianshu.com/p/5f693b4c9468?mType=Group 一.Navicat Premium 12下载 Navicat Premium 12是一套 ...
- Oracle-SQL程序优化4
从事一年DBA工作,经验尚浅,但是遇到问题总还是能够解决,今天就谈下我遇到的一个比较奇葩的问题. 运维人员告知我下午过后ETL一直卡住没有继续,那时我以为又是什么兼容性问题引起的,就重跑一下ETL,谁 ...