谈笑风生
题目大意:
给定a,求任何一个距 a 距离不超过给定的 k 的 b ,然后求一个 c 使得其为 a,b 的后代,求这样的三元组共有多少个。
数据结构好题啊!
解法分析:
我们可以深搜两遍(其实一遍也行),然后对于每个节点去权值线段树上跑一跑,记录 dfs 序,然后就成功地与江大大谈笑风生了。
//by Judge
#include<cstdio>
#include<iostream>
#define ll long long
#define mid (l+r>>1)
using namespace std;
const int M=3e5+7;
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline int read(){ int x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} char sr[1<<21],z[20];int C=-1,Z;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
inline void print(ll x,char chr='\n'){
if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]=chr;
} int n,m,q,p,k,pat,tim,cnt,le,ri,head[M],rt[M];
int dep[M],siz[M],dfn[M],L[M*21],R[M*21]; ll ans,sum[M*21];
struct Edge{ int to,next; }e[M<<1];
inline void add(int u,int v){
e[++pat]={v,head[u]},head[u]=pat;
e[++pat]={u,head[v]},head[v]=pat;
} void update(int las,int& now,int l,int r,int pos,int v){
if(!now) now=++cnt; sum[now]=sum[las]+v; if(l==r) return ;
if(pos<=mid) R[now]=R[las],update(L[las],L[now],l,mid,pos,v);
else L[now]=L[las],update(R[las],R[now],mid+1,r,pos,v);
} ll query(int u,int v,int l,int r,int ql,int qr){
if(l>qr||ql>r) return 0; if(ql<=l&&r<=qr) return sum[v]-sum[u];
return query(L[u],L[v],l,mid,ql,qr)+query(R[u],R[v],mid+1,r,ql,qr);
} inline void cmax(int& a,int b){ if(a<b) a=b; }
#define v e[i].to
void prep(int u,int fa){
siz[u]=1,dep[u]=dep[fa]+1,cmax(m,dep[u]);
for(int i=head[u];i;i=e[i].next)
if(v^fa) prep(v,u),siz[u]+=siz[v];
} void dfs(int u,int fa){ dfn[u]=++tim;
update(rt[tim-1],rt[tim],1,m,dep[u],siz[u]-1);
for(int i=head[u];i;i=e[i].next) if(v^fa) dfs(v,u);
}
int main(){ n=read(),q=read();
for(int i=1,x,y;i<n;++i)
x=read(),y=read(),add(x,y);
for(prep(1,0),dfs(1,0);q;--q){
p=read(),k=read(),le=dfn[p],ri=le+siz[p]-1;
ans=query(rt[le],rt[ri],1,m,dep[p]+1,dep[p]+k);
ans+=1ll*min(dep[p]-1,k)*(siz[p]-1),print(ans);
} return Ot(),0;
}