Description
你有一棵n 节点的树 T,回答 m个询问,每次询问给你两个整数 l r,问存在多少个整数 k使得从l 沿着 l->r
的简单路径走k 步恰好到达k 。
Input
第一行,两个整数n,m表示节点数和询问数。 之后 n-1行,每行两个整数u,v表示一条边。 之后m 行,每行两个整数 l,r 表示 一个询问,题意同题目描述。
Output
m 行,对于每个询问单独输出一行表示你的答案。
Sample explanation
Data Constraint
Limit
时间限制: 3s
空间限制: 512MB
Solution
考虑将一条 L 到 R 的链拆成 L 到 LCA 和 LCA到 R 。
即 d[ x ]表示 x 节点的深度。
则从 L 到 LCA 上答案就是 d[ L ]-d[ x ]=x 的x 的个数,也就是d[ L ]= d[ x ]+x。
已知d[ L ]为定值,则运用树上差分的思想,可以将 root 到 L 路径上的答案减去 root 到 LCA的答案得到。
那么离线在树上dfs的时候用桶记录一下即可。
对于 LCA 到 R 上的答案是 d[ R ]-d[ y ]= len- y 的y的个数,也就是 d[ R ]-len = d[ y ]-y。
同样将询问离线将 根 到 R 的减去 根 到 LCA 的答案即可。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define I int
#define ll long long
#define F(i,a,b) for(register I i=a;i<=b;i++)
#define Fd(i,a,b) for(register I i=a;i>=b;i--)
#define mem(a,b) memset(a,b,sizeof a)
#define N 300005
using namespace std;
I n,m,x,y,z,l[N],r[N],c[N],d[N],t[N<<1],f[N][21],pre[N],suf[N],tot,len,now,ans[N];
I nx[N<<1],ls[N],v[N<<1],cnt,qt[N<<1],ql[N<<1],qnx[N<<1],qls[N];
I R(I &x){
x=0;ll w=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') w=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*=w;
}
void add(I x,I y){
v[++tot]=y,nx[tot]=ls[x],ls[x]=tot;
}
void dg(I x,I y){
f[x][0]=y;d[x]=d[y]+1;t[d[x]+x]++;pre[x]=t[d[x]];
for(I k=ls[x];k;k=nx[k]) if(v[k]!=y){
dg(v[k],x);
}
t[d[x]+x]--;
}
I lca(I x,I y){
if(d[x]<d[y]) swap(x,y);
Fd(i,19,0) if(d[f[x][i]]>=d[y]) x=f[x][i];
if(x==y) return x;
Fd(i,19,0) if(f[x][i]!=f[y][i]){
x=f[x][i],y=f[y][i];
}
return f[x][0];
}
void ins(I x,I len,I id){
qt[++cnt]=id,qnx[cnt]=qls[x],ql[cnt]=len,qls[x]=cnt;
}
void dfs(I x,I y,I op){
(op)?t[d[x]+x]++:t[d[x]-x+n]++;
for(I k=qls[x];k;k=qnx[k]){
now=(op)?t[ql[k]]:t[d[r[qt[k]>m?qt[k]-m:qt[k]]]-ql[k]+n];
if(qt[k]>m) ans[qt[k]-m]-=now;else ans[qt[k]]+=now;
}
for(I k=ls[x];k;k=nx[k]) if(v[k]!=y) dfs(v[k],x,op);
(op)?t[d[x]+x]--:t[d[x]-x+n]--;
}
I main(){
freopen("query.in","r",stdin);
freopen("query.out","w",stdout);
R(n),R(m);
F(i,1,n-1){
R(x),R(y);
add(x,y),add(y,x);
}
dg(1,0);
F(j,1,19){
F(i,1,n) f[i][j]=f[f[i][j-1]][j-1];
}
F(i,1,m){
R(l[i]),R(r[i]);c[i]=lca(l[i],r[i]);
ans[i]=pre[l[i]];
ins(r[i],d[l[i]]+d[r[i]]-2*d[c[i]],i);
ins(c[i],d[l[i]]+d[r[i]]-2*d[c[i]],i+m);
}
dfs(1,0,0);
cnt=0;
mem(qls,0);
F(i,1,m) ins(f[c[i]][0],d[l[i]],i+m);
dfs(1,0,1);
F(i,1,m) printf("%d\n",ans[i]);
return 0;
}