天天爱跑步

题目传送门

借鉴的大佬的博客这儿
个人认为我的解释更详细一些

先来看部分分

$1.$25分

(当然是大暴力了!)

(2.)一条链

首先,要考虑到它有左往右和从右往左两种情况
这里只讨论从左往右的情况,从右往左类似。

若第(i)条路径对(u)点有贡献,当且仅当(dep[u]=dep[si]+w[u])(深度也就等于编号) 移项得(dep[u]-w[u]=dep[si]),可以发现,对(u)产生贡献的点的位置确定。
所以我们开一个(val[])数组,(val[i])表示路径的起点的深度为(i)的路径有多少条。再用两个(vector) (a),(b)记录一下以(i)为起点的路径,和以(i)为终点的路径的起点。
那么在每个节点统计答案(ans[i]=val[dep[i]-w[i]])。(注意用(a),(b)修改(val)数组。)

(3.)所有的(Si=1)

若第(i)条路径对(u)点有贡献,那么需要保证(dep[u]=w[u])。然后(u)的子树中有几个路径的终点,(u)的答案就是几。
(dfs)统计即可。

(4.)所有的(Ti=1)

若第(i)条路径对(u)点有贡献,那么有(dep[si]-dep[u]=w[u]),也就是(dep[u]+w[u]=dep[si])。用(val)数组记录一下深度为(i)的起点有多少个(就是(val[i])表示起点的深度为(i)的路径有多少条)。
接下来对树进行(dfs),那么统计完子树的信息后(val[dep[u]+w[u]])增加的数值就是节点(u)的答案(因为不仅要保证深度满足条件,还要保证(si)(u)的子树内)。

(5.)正解

就是把以上几种情况的思想结合起来。
首先,将一条从(u)(v)的路径拆成从(u)(lca)再从(lca)(v)。这样就分成了向上走和下走两种情况,分别计算。

向上走的情况

若第(i)条路径对(u)点有贡献,那么有(dep[si]-dep[u]=w[u]),也就是(dep[u]+w[u]=dep[si])
借鉴部分分(Ti=1)时的思想,还是用(val)数组记录深度为(i)的起点有多少个。
再借鉴(Si=1)的情况,开一个数组(nums[u])记录一下以(u)为起点的路径有多少条。
因为终点变成了路径的(lca),不再是根节点,所以要考虑的一条(其实是半条)路径结束时的情况,借鉴部分分链时的情况,开一个(vector)(也可以用数组)记录一下以(u)(lca)的所有路径的起点。
然后在(dfs)(u)点时,先(val[dep[u]]+=nums[u]),再将其对应的起点的深度的(val)减一,形象一点就是(:val)([)(u)(LCA)的路径的起点的深度(]--)。答案还是(val[dep[u]+w[u]])增加的数值。

向下走的情况(首先声明(:leni)为第(i)条路径的长度)

若第(i)条路径对(u)点有贡献,那么有(leni-(dep[ti]-dep[u])=w[u]),整理一下得到(dep[u]-w[u]=dep[ti]-leni)
这次(val[X])表示的是满足(dep[ti]-leni=X)的路径有多少条。
用两个(vector)分别在起点和终点记录一下该路径的(dep[t]-len)
然后(dfs)统计答案,方法和上一个差不多。

注意事项

(1.)(dep[u]-w[u])可能会出现负值,不能作为数组的下标,所以要加上一个300000的偏移量。那么问题又来了,(val)数组要开大两倍。
(2.)如果一条路径在(lca)处产生贡献,那么(lca)处要减掉一,因为在向上和向下两种情况中都产生了答案。
(3.)还有最最重要的一条:(dfs)统计答案时一定要先加(以该点为起点的路径),然后统计答案,然后减(在该点结束的路径)。否则会漏掉(w[i]=0)的情况,并且终点处没有统计上答案。
(4.)不要忘了(val)数组清零。

圆满完成!
上代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 300005;
struct node{
	int s,t,lca,len;
}a[N];
int head[N],tot;
struct edge{
	int node,next;
}e[N<<1];
int n,m,w[N],mdep;
vector<int> upper[N],down1[N],down2[N];
int f[N][30],dep[N],ans[N],nums[N],val[N<<1];//val[N]
inline int read()
{
	char c=getchar();
	int ans=0,w=1;
	while((c<'0'||c>'9')&&c!='-') c=getchar();
	if(c=='-') { w=-1; c=getchar(); }
	while(c>='0'&&c<='9')
	{ ans=ans*10+c-'0'; c=getchar(); }
	return ans*w;
}
void add(int x,int y)
{
	e[++tot].node=y; 
	e[tot].next=head[x];
	head[x]=tot;
}
void dfs0(int u,int fa)
{
	f[u][0]=fa;
	dep[u]=dep[fa]+1;
	for(int i=head[u];i;i=e[i].next)
	{
		int v=e[i].node;
		if(v==fa) continue;
		dfs0(v,u);
	}
}
void work()
{
	for(int i=1;i<=19;i++)
	 for(int j=1;j<=n;j++)
	  f[j][i]=f[f[j][i-1]][i-1];
}
int lca(int x,int y)
{
	if(dep[x]<dep[y]) swap(x,y);
	for(int i=19;i>=0;i--)
	 if(dep[f[x][i]]>=dep[y])
	  x=f[x][i];
	if(x==y) return x;
	for(int i=19;i>=0;i--)
	if(f[x][i]!=f[y][i])
	 x=f[x][i],y=f[y][i];
	return f[x][0];
}
inline void dfs3(int u)
{
	int now=dep[u]+w[u],last=val[now];
	for(int i=head[u];i;i=e[i].next)
	 if(e[i].node!=f[u][0])
	  dfs3(e[i].node);
	val[dep[u]]+=nums[u];
	ans[u]=val[now]-last;
	for(int i=0;i<upper[u].size();i++)
	 val[dep[upper[u][i]]]--;
} 
inline void dfs4(int u)
{//cout<<"*";
	int now=dep[u]-w[u]+300000,last=val[now];
	for(int i=head[u];i;i=e[i].next)
	 if(e[i].node!=f[u][0])
	  dfs4(e[i].node);
	for(int i=0;i<down1[u].size();i++)
	 val[down1[u][i]+300000]++;
	ans[u]+=val[now]-last;
	for(int i=0;i<down2[u].size();i++)
	 val[down2[u][i]+300000]--;
}
int main()
{
	n=read(); m=read();
	int x,y;
	for(int i=1;i<n;i++)
	{
		x=read(); y=read();
		add(x,y); add(y,x);
	}
	for(int i=1;i<=n;i++)
	 w[i]=read();
	dfs0(1,0); work();//在前面  
	for(int i=1;i<=m;i++)
	{
		a[i].s=read(); a[i].t=read();
		a[i].lca=lca(a[i].s,a[i].t);
		a[i].len=dep[a[i].s]+dep[a[i].t]-(dep[a[i].lca]<<1);
		nums[a[i].s]++;// dep[a[i].lca<<1] 
		upper[a[i].lca].push_back(a[i].s);
	}
	dfs3(1);
	for(int i=1;i<=m;i++)
	{
		down1[a[i].t].push_back(dep[a[i].t]-a[i].len);
		down2[a[i].lca].push_back(dep[a[i].t]-a[i].len);
	}
	memset(val,0,sizeof(val));
	dfs4(1);
	for(int i=1;i<=m;i++)
	if(dep[a[i].s]==dep[a[i].lca]+w[a[i].lca])
	 ans[a[i].lca]--;
	for(int i=1;i<=n;i++)
	 printf("%d ",ans[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/karryW/p/10864646.html