豪哥生活在一个n个点的树形城市里面,每一天都要走来走去。虽然走的是比较的多,但是豪哥在这个城市里面的朋友并不是很多。
当某一天,猴哥给他展现了一下大佬风范之后,豪哥决定要获得一些交往机会来提升交往能力。豪哥现在已经物色上了一条友,打算和它(豪哥并不让吃瓜群众知道性别)交往。豪哥现在spy了一下这个人的所有行程起点和终点,豪哥打算从终点开始走到起点与其相遇。但是豪哥是想找话题的,他想知道以前有多少次行程和此次行程是有交集的,这样豪哥就可以搭上话了。这个路径与之前路径的有交集数量作为豪哥此次的交往机会。
但是豪哥急着要做交往准备,所以算什么交往机会的小事情就交给你了。
好题。
主要是要发现重要性质:如果两段路径有交,则至少有一段路径的LCA在另外一段路径上。
转化为两个问题:
1)当前LCA在之前路径上 树上差分,树状数组区间修改单点查询
2)当前路径有之前LCA 树上差分,树状数组单点修改区间查询
注意封装树状数组
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<iostream>
#pragma comment(linker,"/STACK:1024000000,1024000000")
using namespace std;
const int N=4e5+10;
struct Front_star{
int u,v,nxt;
}e[N<<1];
int cnt=0;
int first[N];
void add(int u,int v){
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].nxt=first[u];
first[u]=cnt;
}
int dep[N];
int fa[N][21];
int st[N];
int ed[N];
int dfn=0;
void DFS(int u,int fat){
st[u]=++dfn;
fa[u][0]=fat;
for(int i=1;i<=20;++i){
fa[u][i]=fa[fa[u][i-1]][i-1];
}
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==fat)continue;
dep[v]=dep[u]+1;
DFS(v,u);
}
ed[u]=dfn;
}
int LCA(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i=20;i>=0;i--){
if(dep[x]-(1<<i)>=dep[y])x=fa[x][i];
}
if(x==y)return x;
for(int i=20;i>=0;i--){
if(fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][0];
}
int n,m;
struct BIT{
int T[N];
inline int lowbit(int x){
return x&(-x);
}
inline void Update(int x,int val){
while(x<=n){
T[x]+=val;
x+=lowbit(x);
}
}
inline int Query(int x){
int ret=0;
while(x){
ret+=T[x];
x-=lowbit(x);
}
return ret;
}
}A,B;
int val[N];
int GetAns(int u,int v,int lca){
return A.Query(st[u])+A.Query(st[v])-2*A.Query(st[lca])+B.Query(ed[lca])-B.Query(st[lca]-1)+val[lca];
}
int main(){
// freopen("test.in","r",stdin);
int size=40<<20;//40M
__asm__ ("movq %0,%%rsp\n"::"r"((char*)malloc(size)+size));
scanf("%d",&n);
for(int i=1;i<n;++i){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
DFS(1,0);
scanf("%d",&m);
for(int i=1;i<=m;++i){
int u,v;
scanf("%d%d",&u,&v);
int lca=LCA(u,v);
cout<<GetAns(u,v,lca)<<'\n';
val[lca]++;
B.Update(st[u],1);
B.Update(st[v],1);
B.Update(st[lca],-2);
A.Update(st[lca],1);
A.Update(ed[lca]+1,-1);
}
exit(0);
}