题目大意:给你$m$棵由$n$个点构成的全等的树$A$。这$m$棵树之间有$m-1$条边相连,组成了一棵大树。

有$q$组询问,每次询问这棵大树上两点之间的距离。

$n,m,q≤10^5$

这是一道小视野双倍经验题

这一题有一种显然的虚树做法,这种做法我之前打过了,这次换一种做法。

如果询问所在两点在同一棵小树内,那么显然直接倍增就可以了。

我们将连接$m$棵树的边抽出来,构成另外一棵树(暂且称作树$B$),节点$p$表示第$p$棵树,我们钦定这棵树的$1$号点为根。

我们令$up1[i]$表示树$B$中,连接$i$号点$father$所在的边,它在第$i$棵小树中所连接的节点。

令$up2[i]$表示树$B$中,连接$i$号点$father$所在的边,它在第$fa[i]$棵小树中所连接的点。

令$dis[i]$表示从树$B$的第$1$号树的$1$号节点开始,到达小树$i$第$up1[i]$号节点的距离。

对于一组询问$(w,x,y,z)$,我们求出$w,y$的$lca$,令$w'$表示在$w$到$lca$的路径上,离$lca$最近的点(不包括$lca$本身),同理求出$y'$。

设最终答案为$ans$

若存在$w'$,则$ans+=A.dis(x,up1[x])+dis[w]-dis[w']$,并令$x=up2[w']$。

若存在$y'$,则$ans+=A.dis(z,up1[z])+dis[y]-dis[y']$,并令$z=up2[y']$。

最后$ans+=A.dis(x,z)$即可。

注意细节

 #include<bits/stdc++.h>
#define M 100005
#define L long long
using namespace std;
int n,m,q;
struct tree1{
struct edge{int u,next;}e[M*]; int head[M],use=;
void add(int x,int y){use++;e[use].u=y;e[use].next=head[x];head[x]=use;}
int f[M][],dep[M];
void dfs(int x,int fa){
f[x][]=fa; dep[x]=dep[fa]+;
for(int i=;i<;i++) f[x][i]=f[f[x][i-]][i-];
for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa) dfs(e[i].u,x);
}
int getlca(int x,int y){
if(dep[x]<dep[y]) swap(x,y); int cha=dep[x]-dep[y];
for(int i=;~i;i--) if((<<i)&cha) x=f[x][i];
for(int i=;~i;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
if(x==y) return x; return f[x][];
}
int getdis(int x,int y){
int lca=getlca(x,y);
return dep[x]+dep[y]-*dep[lca];
}
void init(){
for(int i=;i<n;i++){
int x,y; scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
dfs(,);
}
}a;
struct tree2{
struct edge{int u,us,ut,next;}e[M*]; int head[M],use=;
void add(int x,int y,int us,int ut){use++;e[use].u=y;e[use].us=us;e[use].ut=ut;e[use].next=head[x];head[x]=use;}
int f[M][],dep[M],up1[M],up2[M]; L dis[M];
void dfs(int x,int fa){
f[x][]=fa; dep[x]=dep[fa]+;
for(int i=;i<;i++) f[x][i]=f[f[x][i-]][i-];
for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa){
up1[e[i].u]=e[i].ut; up2[e[i].u]=e[i].us;
dis[e[i].u]=dis[x]+a.getdis(up1[x],e[i].us)+;
dfs(e[i].u,x);
}
}
int getlca(int x,int y){
if(dep[x]<dep[y]) swap(x,y); int cha=dep[x]-dep[y];
for(int i=;~i;i--) if((<<i)&cha) x=f[x][i];
for(int i=;~i;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
if(x==y) return x; return f[x][];
}
int jump(int x,int k){
for(int i=;~i;i--) if((<<i)&k) x=f[x][i];
return x;
}
void init(){
for(int i=;i<m;i++){
int x,X,y,Y; scanf("%d%d%d%d",&x,&X,&y,&Y);
add(x,y,X,Y); add(y,x,Y,X);
}
dfs(,);
}
}b;
int main(){
scanf("%d%d%d",&n,&m,&q);
a.init();
b.init();
while(q--){
int x,X,y,Y; scanf("%d%d%d%d",&x,&X,&y,&Y);
int lca=b.getlca(x,y);
L ans=;
if(x!=lca){
ans+=a.getdis(X,b.up1[x]);
int xx=b.jump(x,b.dep[x]-b.dep[lca]-);
ans+=b.dis[x]-b.dis[xx]+;
X=b.up2[xx];
}
if(y!=lca){
ans+=a.getdis(Y,b.up1[y]);
int yy=b.jump(y,b.dep[y]-b.dep[lca]-);
ans+=b.dis[y]-b.dis[yy]+;
Y=b.up2[yy];
}
ans+=a.getdis(X,Y);
printf("%lld\n",ans);
}
}

【xsy1156】 树套树(tree) 倍增的更多相关文章

  1. bzoj3262: 陌上花开(树套树)

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

  2. 树套树专题——bzoj 3110: [Zjoi2013] K大数查询 &amp; 3236 [Ahoi2013] 作业 题解

    [原题1] 3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 978  Solved: 476 Descri ...

  3. BZOJ_3196_二逼平衡树_(树套树,线段树+Treap)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=3196 可以处理区间问题的平衡树. 3196: Tyvj 1730 二逼平衡树 Time Lim ...

  4. bzoj 3295: [Cqoi2011]动态逆序对(树套树 or CDQ分治)

    Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计 ...

  5. BZOJ3110 [Zjoi2013]K大数查询 树套树 线段树 整体二分 树状数组

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3110 题意概括 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位 ...

  6. 【bzoj1901】dynamic ranking(带修改主席树/树套树)

    题面地址(权限题) 不用权限题的地址 首先说说怎么搞带修改主席树? 回忆一般的kth问题,我们的主席树求的是前缀和,这样我们在目标区间的左右端点的主席树差分下就能求出kth. 那么我们如何支持修改操作 ...

  7. Dynamic Rankings(动态第k大+树套树)

    题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1112 题目: 思路: 树套树板子题. 代码实现如下: #inclu ...

  8. Educational Codeforces Round 56 (Rated for Div. 2) E(1093E) Intersection of Permutations (树套树,pb_ds)

    题意和分析在之前的链接中有:https://www.cnblogs.com/pkgunboat/p/10160741.html 之前补题用三维偏序的cdq的分治A了这道题,但是感觉就算比赛再次遇到类似 ...

  9. 树套树Day2

    滚回来更新,,, 在Day1我们学了最基本的线段树套平衡树 Day2开始我们要学习一些黑科技 (所以很大概率会出现Day3 w 1.线段树上的黑科技 这一段我们分几项来讲 1.权值线段树 权值线段树以 ...

  10. 树套树Day1线段树套平衡树bzoj3196

    您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查 ...

随机推荐

  1. Java中创建数组的几种方法

    Java中创建数组的几种方法 public static void main(String[] args) { //创建数组的第一种方法 int[] arr=new int[6]; int intVa ...

  2. 2018.10.20 loj#2593. 「NOIP2010」乌龟棋(多维dp)

    传送门 f[i][j][k][l]f[i][j][k][l]f[i][j][k][l]表示用iii张111,jjj张222,kkk张333,lll张444能凑出的最大贡献. 然后从f[i−1][j][ ...

  3. 2018.09.23 bzoj3143: [Hnoi2013]游走(dp+高斯消元)

    传送门 显然只需要求出所有边被经过的期望次数,然后贪心把边权小的边定城大的编号. 所以如何求出所有边被经过的期望次数? 显然这只跟边连接的两个点有关. 于是我们只需要求出两个点被经过的期望次数. 对于 ...

  4. LA 3213 Ancient Cipher (水题,转化)

    题意:给定两个长度相同的字符串,判断它们之间是否存在一一对应关系,顺序不定. 析:刚开始没看到顺序不定,然后写完没胡把样例看完就交了,结果WA了一次...其实这是一个水题,既然顺序不定,那么更简单,我 ...

  5. Spring3.x错误----Bean named "txAdvice" must be of type[org.aopallibance.aop.Advice

    Spring3.x错误: 解决方法: aopalliance-1.0.jar 和 aopalliance-alpha1.jar之间的冲突.

  6. ansible api 调用出现ssh交互式输入

    发现在删掉 ~/.ssh/know_hosts 之后运行 ansible api 会出现以下提示 The authenticity of host '10.1.*.* (10.1.*.*)' can' ...

  7. Hdu1361&&Poj1068 Parencodings 2017-01-18 17:17 45人阅读 评论(0) 收藏

    Parencodings Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total ...

  8. IDEA14/Eclipse+Tomcat7热部署,jrebel6破解与eclipse配置

    换了最新的eclipse,以前很多的插件都用不了,对于web开发的人来说,jrebel这种防重启神器必须要配备,防止修改类名.java文件.配置文件后的tomcat重启. 首先给一个下载地址: htt ...

  9. cheerio笔记

    不会的东西,再简单都是难:会的东西,再难都是简单. 给自己写的,写的通俗易懂. cheerio:在node服务端,解析网页,是jquery的核心,去除了DOM中不一致的地方. 先获得网页的源码,再通过 ...

  10. Android-Android7.0-java.lang.SecurityException: MODE_WORLD_READABLE no longer supported

    某个AndroidProject项目在Android5.0系统运行是OK的,在Android7.0以上版本运行,报以下错误❌ 2019-01-02 15:33:39.996 17067-17067/? ...