Luogu P3066 [USACO12DEC] Running Away From the Barn G (LCA + two points + difference)

Topic link

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 longcode, because the open long longcode 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;
}

Guess you like

Origin blog.csdn.net/Brian_Pan_/article/details/110928431