解题思路:
考虑差值直接搞不好维护,那么就确定好最大值,这样就确定了整棵树所有可枚举的点集。
考虑确定了以一个点点权为上界时一定可以拓展出一个以这个点为根的树状联通块。
现在就需要统计一棵树中所有包含根节点的树形图的个数。
考虑序列上怎么统计,当关键点为序列端点时,那就是序列长度。
关键点为序列中间点时,答案就是
(
a
n
s
l
+
1
)
∗
(
a
n
s
r
+
1
)
(ansl+1)*(ansr+1)
(ansl+1)∗(ansr+1),理解为左侧有
[
0
,
l
]
[0,l]
[0,l]共l+1种选法,右侧同理
树上就是
f
x
=
∏
y
∈
s
o
n
x
(
f
y
+
1
)
\Large f_x=\prod\limits_{y\in son_x}(f_y+1)
fx=y∈sonx∏(fy+1)
每个点跑一边dfs统计
f
x
f_x
fx输出就好了。
注意那个上界应该是一种严格的比较,所以当点权相同时使用编号作为第二关键字就好了。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long lnt;
const lnt mod=1000000007;
struct pnt{
int hd;
int a;
lnt f;
}p[2001];
struct ent{
int twd;
int lst;
}e[5000];
lnt ans;
int n,d;
int cnt;
void ade(int f,int t)
{
cnt++;
e[cnt].twd=t;
e[cnt].lst=p[f].hd;
p[f].hd=cnt;
return ;
}
void dfs(int x,int f,int r)
{
p[x].f=1;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==f)continue;
if(p[to].a>p[r].a)continue;
if(p[to].a<p[r].a-d)continue;
if(p[to].a==p[r].a&&to<r)continue;
dfs(to,x,r);
p[x].f=(p[x].f*(p[to].f+1))%mod;
}
return ;
}
int main()
{
scanf("%d%d",&d,&n);
for(int i=1;i<=n;i++)scanf("%d",&p[i].a);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ade(x,y);ade(y,x);
}
for(int i=1;i<=n;i++)
{
dfs(i,i,i);
(ans+=p[i].f)%=mod;
}
printf("%I64d\n",ans);
return 0;
}