首先考虑给定的a点,那么b点的位置只可能是a的祖先或者a的不大于k层的儿子
对于祖先,答案很好统计,而对于儿子,就要考虑维护dfs序
对于给定的p,k,儿子部分的答案为整颗子树中深度不大于dep[p]+k所有sz[v]-1的和
所以很容易想到维护一颗树套树或者可持久化线段树
但是数据范围有30w,树套树肯定会超时,可持久化线段树常数也很大(即标程)
所以我的做法就在这里考虑离线处理
我们对所有询问的dep[p]+k排序,依次加点即可
神奇的是,我的暴力速度在随机数据下和我的程序差不到一倍,可惜被卡了。。。。。。。。。。。。。
速度比标程快一倍
注意dfs的时候需要手工栈
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <stack>
using namespace std;
#define rep(i,l,r) for(int i=(l),_=(r);i<=_;i++)
#define per(i,r,l) for(int i=(r),_=(l);i>=_;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define INE(i,u) for(int i=head[u];~i;i=e[i].next)
#define LL long long
inline const int read()
{int r=0,k=1;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';return k*r;}
const int N=310010;
int n,q;
struct edge{int v,next;}e[N*2];
int head[N],k;
int fa[N],dep[N],sz[N];
int in[N],out[N],dfs_clock;
struct query{int p,k,id;}qry[N];
LL ans[N];
int dhead[N],pt[N],next[N],kk;
LL sum[N*2];
LL getsum(int l,int r)
{
LL s=0;
for(;r;r-=r&-r) s+=sum[r];
for(l--;l;l-=l&-l) s-=sum[l];
return s;
}
void insert(int o,int x)
{
for(;o<=2*n;o+=o&-o) sum[o]+=x;
}
void add(int d)
{
for(int i=dhead[d];~i;i=next[i])
insert(in[pt[i]],sz[pt[i]]-1);
}
bool cmp(query a,query b){return dep[a.p]+a.k < dep[b.p]+b.k;}
void adde(int u,int v){e[k]=(edge){v,head[u]};head[u]=k++;}
void dfs()
{
stack<int>s;
s.push(1);
while(!s.empty())
{
int u=s.top(),f=0;
if(!in[u]) in[u]=++dfs_clock;
sz[u]=1;
INE(i,u)
{
int v=e[i].v; if(v==fa[u] || in[v]) continue;
fa[v]=u;
dep[v]=dep[u]+1;
s.push(v);
f=1;
}
if(!f)
{
out[u]=++dfs_clock;
INE(i,u)
{
int v=e[i].v; if(v==fa[u]) continue;
sz[u]+=sz[v];
}
s.pop();
}
}
}
void init_d()
{
rep(i,1,n)
{
int d=dep[i];
kk++;
pt[kk]=i;
next[kk]=dhead[d];
dhead[d]=kk;
}
}
void input()
{
MS(head,-1); MS(dhead,-1);
cin>>n>>q;
rep(i,1,n-1)
{
int u=read(), v=read();
adde(u,v); adde(v,u);
}
}
void solve()
{
dfs();
init_d();
rep(i,1,q)
{
int p=read(), k=read();
qry[i]=(query){p,k,i};
ans[i]+=(LL)min(dep[p],k) * (sz[p]-1);
}
sort(&qry[1],&qry[q+1],cmp);
int cur=0;
rep(i,1,q)
{
while(cur<dep[qry[i].p]+qry[i].k) add(++cur);
if(in[qry[i].p]+1 <= out[qry[i].p]-1)
ans[qry[i].id]+=getsum(in[qry[i].p]+1,out[qry[i].p]-1);
}
rep(i,1,q) printf("%I64d\n",ans[i]);
}
int main()
{
freopen("laugh.in","r",stdin); freopen("laugh.out","w",stdout);
input(),solve();
return 0;
}