題意太長 不贅述
考慮如何去求三元組(a,b,c)
1.b是a的祖先 這個很好算 因爲a的每個兒子都可以作爲c 然後b和a的距離不超過k就行 顯然就是
2.a是b的祖先 這個纔是這題的難度所在
設tid[x]爲x的dfs序
如果a是b的祖先
並且 依題意
這就變成了一個二維數點的模型 以tid爲x軸 dep爲y軸 那不就是在矩形 (tid[a],dep[a]), (tid[a]+siz[a]-1,dep[a]+k)裏面有多少個點嗎 對於每個合法的b點 對答案的貢獻顯然是
用樹狀數組維護就行了 如果想在線搞得話 主席樹就行
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+100;
typedef long long ll;
int h[N],nex[N<<1],to[N<<1],cur;
int n,q,dep[N],siz[N],tid[N],dfn,tot;
ll c[N],res[N];
void add(int x,ll val){
while(x<=n){
c[x]+=val;
x+=x&-x;
}
}
ll query(int x){
ll ret=0;
while(x){
ret+=c[x];
x-=x&-x;
}
return ret;
}
void add_edge(int x,int y){
to[++cur]=y;nex[cur]=h[x];h[x]=cur;
}
void dfs(int u,int fa){
siz[u]=1;dep[u]=dep[fa]+1;tid[u]=++dfn;
for(int i = h[u]; i; i = nex[i]){
int v = to[i];
if(v==fa) continue;
dfs(v,u);
siz[u]+=siz[v];
}
}
struct node{
int sz,de,ti;
bool operator <(const node& a)const{
return de<a.de;
}
}T[N];
struct line{
int l,r,h,id,op;
bool operator < (const line& a)const{
return h<a.h;
}
}p[N<<1];
int main(){
scanf("%d%d",&n,&q);
for(int i = 1; i <= n-1; i++){
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);add_edge(v,u);
}
dfs(1,0);
for(int i = 1; i <= n; i++) T[i]=(node){siz[i]-1,dep[i],tid[i]};
for(int i = 1; i <= q; i++){
int x,y;
scanf("%d%d",&x,&y);
p[++tot]={tid[x],tid[x]+siz[x]-1,dep[x],i,-1};
p[++tot]={tid[x],tid[x]+siz[x]-1,dep[x]+y,i,1};
res[i]+=1ll*(siz[x]-1)*min(dep[x]-1,y);
}
sort(p+1,p+1+tot);
sort(T+1,T+1+n);
for(int i = 1,j = 1; i <= tot; i++){
while(j<=n&&T[j].de<=p[i].h) add(T[j].ti,T[j].sz),j++;
res[p[i].id]+=1ll*p[i].op*(query(p[i].r)-query(p[i].l));
}
for(int i = 1; i <= q; i++) printf("%lld\n",res[i]);
return 0;
}