为了学长链剖分开的题,结果还是忍不住写了个线段树合并
首先不难发现:$b$ 要么是 $a$ 的祖先,要么是 $a$ 的后代。
$b$ 是 $a$ 的祖先很好弄,因为 $c$ 的数量始终等于 $size_a-1$;对于 $b$ 要么是 $a$ 的后代的情况,那么就是求 $a$ 的子树中和它深度差不超过 $k$ 的点的 $size-1$ 之和,按照深度插进线段树以后合并一下即可。
#include#include #define For(i,A,B) for(i=(A);i<=(B);++i) using namespace std; typedef long long ll; const int N=300050; const int BUF=1<<21; char rB[BUF],*rS,*rT,wB[BUF+50]; int wp=-1; inline char gc(){return rS==rT&&(rT=(rS=rB)+fread(rB,1,BUF,stdin),rS==rT)?EOF:*rS++;} inline void flush(){fwrite(wB,1,wp+1,stdout);wp=-1;} inline int rd(){ char c=gc(); while(c<48||c>57)c=gc(); int x=c&15; for(c=gc();c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c&15); return x; } short buf[25]; inline void wt(ll x){ if(wp>BUF)flush(); short l=-1; while(x>9){ buf[++l]=x%10; x/=10; } wB[++wp]=x|48; while(l>=0)wB[++wp]=buf[l--]|48; wB[++wp]='\n'; } int G[N],to[N<<1],nxt[N<<1],sz,dep[N],siz[N],rt[N],lc[N*20],rc[N*20],tot,n; ll sum[N*20],s[N]; vector<int> k[N],id[N]; inline int Min(int a,int b){return aa:b;} inline void adde(int u,int v){ to[++sz]=v;nxt[sz]=G[u];G[u]=sz; to[++sz]=u;nxt[sz]=G[v];G[v]=sz; } void add(int &o,int L,int R,int x,int k){ if(!o)o=++tot; sum[o]+=k; if(L<R){ int M=L+R>>1; if(x<=M)add(lc[o],L,M,x,k); else add(rc[o],M+1,R,x,k); } } int merg(int u,int v){ if(!u||!v)return u|v; sum[u]+=sum[v]; lc[u]=merg(lc[u],lc[v]);rc[u]=merg(rc[u],rc[v]); return u; } ll query(int o,int L,int R,int x,int y){ if(!o)return 0ll; if(x<=L&&y>=R)return sum[o]; int M=L+R>>1; ll ans=0ll; if(x<=M)ans=query(lc[o],L,M,x,y); if(y>M)ans+=query(rc[o],M+1,R,x,y); return ans; } void dfs(int u,int fa){ int i,v; dep[u]=dep[fa]+1; siz[u]=1; for(i=G[u];i;i=nxt[i])if((v=to[i])!=fa){ dfs(v,u); rt[u]=merg(rt[u],rt[v]); siz[u]+=siz[v]; } For(i,0,(int)k[u].size()-1)s[id[u][i]]=query(rt[u],1,n,dep[u]+1,Min(n,dep[u]+k[u][i]))+(ll)Min(dep[u]-1,k[u][i])*(siz[u]-1); add(rt[u],1,n,dep[u],siz[u]-1); } int main(){ int q,i,u,v; n=rd();q=rd(); For(i,2,n){ u=rd();v=rd(); adde(u,v); } For(i,1,q){ u=rd();v=rd(); k[u].push_back(v);id[u].push_back(i); } dfs(1,0); For(i,1,q)wt(s[i]); flush(); return 0; }