我也不知道题面的引申意义
发现可以求出以每个点为p时的ans,讨论一下祖先和子孙的贡献,用长链剖分维护就好了
Code:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=3e5+5;
int vis[N<<1],nxt[N<<1],head[N<<1],tot=0;
int val[N],pt[N],fa[N],lson[N],top[N],md[N],dep[N],siz[N];
ll tmp[N],*f[N],*id=tmp,ans[N];
struct Q{int num,k;};
vector<Q>q[N];
inline void add(int x,int y){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
void dfs(int v){
pt[v]=siz[v]=1;
for(int i=head[v];i;i=nxt[i]){
int y=vis[i];
if(pt[y]) continue;
fa[y]=v;md[y]=dep[y]=dep[v]+1;
dfs(y);
siz[v]+=siz[y];
if(md[y]>md[lson[v]]) lson[v]=y;
}
if(lson[v]) md[v]=md[lson[v]];
}
void dp(int v){
f[v][0]=siz[v]-1;
if(lson[v]) f[lson[v]]=f[v]+1,dp(lson[v]),f[v][0]+=f[lson[v]][0];
for(int i=head[v];i;i=nxt[i]){
int y=vis[i];
if(y==fa[v] || y==lson[v]) continue;
f[y]=id;id+=md[y]-dep[y]+1;
dp(y);
for(int j=0;j<=md[y]-dep[y];j++) f[v][j+1]+=f[y][j];
f[v][0]+=f[y][0];
}
for(int i=q[v].size()-1;~i;i--){
int k=q[v][i].k,num=q[v][i].num;
ans[num]+=1ll*(siz[v]-1)*min(dep[v]-1,k);
if(k>=md[v]-dep[v]) ans[num]+=f[v][0]-siz[v]+1;
else ans[num]+=f[v][0]-siz[v]+1-f[v][k+1];
}
return;
}
int n,m;
int main(){
n=read(),m=read();
for(int x,y,i=1;i<n;i++){x=read(),y=read();add(x,y);add(y,x);}
dep[1]=1;dfs(1);
for(int i=1;i<=m;i++) {int u=read();Q t;t.k=read();t.num=i;q[u].push_back(t);}
f[1]=id;id+=md[1];dp(1);
for(int i=1;i<=m;i++) cout<<ans[i]<<"\n";
return 0;
}