#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#define Inf 0x3f3f3f3f
using namespace std;
const int maxn = 10010;
const int maxm = 50010;
const int p = 1e9+7;
struct Edge {
int u, v;
int next;
}e[maxn];
struct Node {
int sum, add, mul;
}a[maxn*3];
int n, m, ncnt;
int fi[maxn], ecnt;
int dep[maxn], siz[maxn], top[maxn], fa[maxn], son[maxn], tid[maxn];
int array[maxn], rank[maxn];
void add_edge(int u, int v) {
e[++ecnt] = (Edge){u, v, fi[u]};
fi[u]= ecnt;
}
void dfs1(int x, int Fa, int d) {
dep[x] = d;
fa[x] = Fa;
siz[x] = 1;
for(int i = fi[x]; i != -1; i = e[i].next) {
int v = e[i].v;
dfs1(v, x, d+1);
siz[x] += siz[v];
if(son[x] == -1 || siz[son[x]] < siz[v])
son[x] = v;
}
}
void dfs2(int x, int tp) {
top[x] = tp;
tid[x] = ++ncnt;
rank[ncnt] = x;
if(son[x] == -1)
return;
dfs2(son[x], tp);
for(int i = fi[x]; i != -1; i = e[i].next) {
int v = e[i].v;
if(son[x] != v && v != fa[x])
dfs2(v, v);
}
}
void push_down(int o, int l, int r) {
int M = l + (r-l)/2;
a[o*2].add = (a[o*2].mul*a[o].mul + a[o].add)%p;
a[o*2+1].add = (a[o*2+1].add*a[o].mul + a[o].add)%p;
a[o*2].mul = (a[o*2].mul*a[o].mul)%p;
a[o*2+1].mul = (a[o*2+1].mul*a[o].mul)%p;
a[o*2].sum = (a[o].add*(M-l+1)%p + a[o].mul*a[o*2].sum%p)%p;
a[o*2+1].sum = (a[o].add*(r-M)%p + a[o].mul*a[o*2+1].sum%p)%p;
a[o].add = 0; a[o].mul = 1;
}
void build_tree(int o, int l, int r) {
a[o].mul = 1;
if(l == r) {
a[o].sum = array[rank[l]];
return;
}
int M = l + (r-l)/2;
build_tree(o*2, l, M);
build_tree(o*2+1, M+1, r);
a[o].sum = (a[o*2].sum+a[o*2+1].sum)%p;
}
void add_tree(int o, int l, int r, int L, int R, int k) {
if(l >= L && r <= R) {
a[o].sum = (a[o*2+1].sum+k*(r-l+1))%p;
a[o].add = (k + a[o].add)%p;
return;
}
push_down(o, l, r);
int M = l + (r-l)/2;
if(L <= M)
add_tree(o*2, l, M, L, R, k);
if(R > M)
add_tree(o*2+1, M+1, r, L, R, k);
a[o].sum = (a[o*2].sum + a[o*2+1].sum)%p; //update
return;
}
void mul_tree(int o, int l, int r, int L, int R, int k) {
if(l >= L && r <= R) {
a[o].add = a[o].add*k%p;
a[o].sum = a[o].sum*k%p;
a[o].mul = a[o].mul*k%p;
return;
}
push_down(o, l, r);
int M = l + (r-l)/2;
if(L <= M)
mul_tree(o*2, l, M, L, R, k);
if(R > M)
mul_tree(o*2+1, M+1, r, L, R, k);
a[o].sum = (a[o*2].sum + a[o*2+1].sum)%p;
return;
}
long long query(int o, int l, int r, int L, int R) {
if(l >= L && r <= R)
return a[o].sum%p;
push_down(o, l, r);
long long ans = 0;
int M = l + (r-l)/2;
if(L <= M)
query(o*2, l, M, L, R);
if(R > M)
query(o*2+1, M+1, r, L, R);
return ans%p;
}
int main() {
memset(son, -1, sizeof(son));
memset(fi, -1, sizeof(fi));
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &array[i]);
for(int i = 1; i <= n-1; i++) {
int u, v;
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
dfs1(1, -1, 1);
dfs2(1, 1);
}
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#define Inf 0x3f3f3f3f
using namespace std;
const int maxn = 10010;
const int maxm = 50010;
const int p = 1e9+7;
struct Edge {
int u, v;
int next;
}e[maxn];
struct Node {
int sum, add, mul;
}a[maxn*3];
int n, m, ncnt;
int fi[maxn], ecnt;
int dep[maxn], siz[maxn], top[maxn], fa[maxn], son[maxn], tid[maxn];
int array[maxn], rank[maxn];
void add_edge(int u, int v) {
e[++ecnt] = (Edge){u, v, fi[u]};
fi[u]= ecnt;
}
void dfs1(int x, int Fa, int d) {
dep[x] = d;
fa[x] = Fa;
siz[x] = 1;
for(int i = fi[x]; i != -1; i = e[i].next) {
int v = e[i].v;
dfs1(v, x, d+1);
siz[x] += siz[v];
if(son[x] == -1 || siz[son[x]] < siz[v])
son[x] = v;
}
}
void dfs2(int x, int tp) {
top[x] = tp;
tid[x] = ++ncnt;
rank[ncnt] = x;
if(son[x] == -1)
return;
dfs2(son[x], tp);
for(int i = fi[x]; i != -1; i = e[i].next) {
int v = e[i].v;
if(son[x] != v && v != fa[x])
dfs2(v, v);
}
}
void push_down(int o, int l, int r) {
int M = l + (r-l)/2;
a[o*2].add = (a[o*2].mul*a[o].mul + a[o].add)%p;
a[o*2+1].add = (a[o*2+1].add*a[o].mul + a[o].add)%p;
a[o*2].mul = (a[o*2].mul*a[o].mul)%p;
a[o*2+1].mul = (a[o*2+1].mul*a[o].mul)%p;
a[o*2].sum = (a[o].add*(M-l+1)%p + a[o].mul*a[o*2].sum%p)%p;
a[o*2+1].sum = (a[o].add*(r-M)%p + a[o].mul*a[o*2+1].sum%p)%p;
a[o].add = 0; a[o].mul = 1;
}
void build_tree(int o, int l, int r) {
a[o].mul = 1;
if(l == r) {
a[o].sum = array[rank[l]];
return;
}
int M = l + (r-l)/2;
build_tree(o*2, l, M);
build_tree(o*2+1, M+1, r);
a[o].sum = (a[o*2].sum+a[o*2+1].sum)%p;
}
void add_tree(int o, int l, int r, int L, int R, int k) {
if(l >= L && r <= R) {
a[o].sum = (a[o*2+1].sum+k*(r-l+1))%p;
a[o].add = (k + a[o].add)%p;
return;
}
push_down(o, l, r);
int M = l + (r-l)/2;
if(L <= M)
add_tree(o*2, l, M, L, R, k);
if(R > M)
add_tree(o*2+1, M+1, r, L, R, k);
a[o].sum = (a[o*2].sum + a[o*2+1].sum)%p; //update
return;
}
void mul_tree(int o, int l, int r, int L, int R, int k) {
if(l >= L && r <= R) {
a[o].add = a[o].add*k%p;
a[o].sum = a[o].sum*k%p;
a[o].mul = a[o].mul*k%p;
return;
}
push_down(o, l, r);
int M = l + (r-l)/2;
if(L <= M)
mul_tree(o*2, l, M, L, R, k);
if(R > M)
mul_tree(o*2+1, M+1, r, L, R, k);
a[o].sum = (a[o*2].sum + a[o*2+1].sum)%p;
return;
}
long long query(int o, int l, int r, int L, int R) {
if(l >= L && r <= R)
return a[o].sum%p;
push_down(o, l, r);
long long ans = 0;
int M = l + (r-l)/2;
if(L <= M)
query(o*2, l, M, L, R);
if(R > M)
query(o*2+1, M+1, r, L, R);
return ans%p;
}
int main() {
memset(son, -1, sizeof(son));
memset(fi, -1, sizeof(fi));
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &array[i]);
for(int i = 1; i <= n-1; i++) {
int u, v;
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
dfs1(1, -1, 1);
dfs2(1, 1);
}