题目大意:给你$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. Linux操作系统Vim代码Tab自动补全配置

    function! CleverTab() , col( ) =~ '^\s*$' return "\<Tab>" else return "\<C-N ...

  2. QQ使用技巧

    1.改变真实地理位置 大家知道,现在很多QQ都是显示IP和地理位置的版本,这样一来,自己的位置就暴露了.其实想隐藏自己的位置也简单,只要用代理服务器就是了.不要把它看成很复杂的东西,建议去下载&quo ...

  3. 2018.10.15 NOIP训练 hyc的等比数列(数论+枚举)

    传送门 一道不错的枚举题. 显然桶排序之后瞎枚举一波. 考虑枚举首项和末项,假设首项除去一个最大的平方因子得到的结果为xxx. 那么末项一定等于xxx乘上一个平方数. 于是我们枚举首项,算出xxx然后 ...

  4. Python网络编程总结

    ----learn from luffycity---- 1. 什么是C/S架构? C指的是client(客户端软件),S指的是Server(服务端软件),C/S架构就是基于网络实现客户端与服务端通信 ...

  5. DDR的型号问题

    一.DDR的容量大小 先看下micron公司对DDR3命名的规则: 1.meg的含义: 内存中Meg的含义:Meg就是兆的含义,即1000,000. MT47H64M16 – 8 Meg x 16 x ...

  6. qq强制聊天工具

    当你想和别人聊天, 别人有不理你的时候可以用上哦!!!特别是情人吵架的时候, 呵呵 复制下面的代码: @echo off title DIY-QQ强制聊天工具color 0a echo. echo.  ...

  7. Java中JNI的使用详解第一篇:HelloWorld

    转自: http://blog.csdn.net/jiangwei0910410003/article/details/17465085 今天开始研究JNI技术,首先还是老套路,输出一个HelloWo ...

  8. MFC中添加新的对话框

    MFC工程中,除了系统自动生成的一些对话框之外,还需要根据自己的需求,添加新的对话框.这里总结下自己最近使用的方法. 首先,找到Resource View中自己新建的工程,然后右键,选择Add Cla ...

  9. 移动 APP 网络优化概述

    一般开发一个 APP,会直接调用系统提供的网络请求接口去服务端请求数据,再针对返回的数据进行一些处理,或者使用AFNetworking/OKHttp这样的网络库,管理好请求线程和队列,再自动做一些数据 ...

  10. java实现WC项目

    个人项目:WC   wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要求写一个命令行程序,模仿已有wc.exe 的功能,并加以扩充,给出某程序设计语言源文件的字符数.单 ...