I just saw this question and thought it was a line segment tree merging, and then I discovered the sideband weight
We consider each point’s contribution to others, that is, how many nodes it counts into the answer.
For a point xxx , obviously he can onlydeal with xxThe point on the path from x to the root contributes. Since the point on this path is away fromxxThe distance of x satisfies the monotonicity, so it is affected byxxThe contribution node of x must be fromxxA continuous segment of nodes starting from x .
Then, we consider dfs to maintain the current nodexxNodes on the path from x to the root, and use dichotomy + LCA to find out which ones contribute to, and finally maintain the answer of each node with the difference on the tree
Posted here are not open long long
code, because the open long long
code ugly
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int Maxn=200010;
const int Maxm=Maxn<<1;
int c[Maxn],d[Maxn];
int f[Maxn][20];
int dis[Maxn],head[Maxn];
int s[Maxn],nxt[Maxm];
int to[Maxm],len[Maxm];
int n,m,edgecnt,cnt;
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;ch=getchar();}
while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return s*w;
}
inline void add(int x,int y,int c)
{
++edgecnt;
nxt[edgecnt]=head[x];
to[edgecnt]=y;
len[edgecnt]=c;
head[x]=edgecnt;
}
int find(int x,int y)
{
while(d[x]!=d[y])
{
if(d[x]<d[y])swap(x,y);
for(int i=18;i>=0;--i)
if(d[f[x][i]]>=d[y])x=f[x][i];
}
if(x==y)return x;
for(int i=18;i>=0;--i)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
int dist(int x,int y)
{
int pos=find(x,y);
return dis[x]+dis[y]-(dis[pos]<<1);
}
void dfs(int x,int fa,int pre)
{
d[x]=d[fa]+1;
dis[x]=dis[fa]+pre;
f[x][0]=fa;
for(int i=1;i<=18;++i)
f[x][i]=f[f[x][i-1]][i-1];
c[++cnt]=x;
int l=1,r=cnt;
while(l<r)
{
int mid=(l+r)>>1;
if(dist(x,c[mid])>m)l=mid+1;
else r=mid;
}
++s[x],--s[f[c[l]][0]];
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==fa)continue;
dfs(y,x,len[i]);
}
--cnt;
}
void work(int x,int fa)
{
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==fa)continue;
work(y,x),s[x]+=s[y];
}
}
int main()
{
// freopen("in.txt","r",stdin);
n=read(),m=read();
for(int i=2;i<=n;++i)
{
int x=read(),val=read();
add(x,i,val),add(i,x,val);
}
dfs(1,0,0);
work(1,0);
for(int i=1;i<=n;++i)
printf("%lld\n",s[i]);
return 0;
}