题意:有一棵以1为root,n个节点的根树,然后存在一个有n个数字的数组x,询问从i节点最多走 x [ i ] x[i] x[i]步可以最多到达几个父亲上的点,然后数组n个数字,分别为从 1 , 2 , … n 1, 2, \dots n 1,2,…n出发可以最多到达几个点。
题解:
首先我们定义
d
e
p
[
i
]
dep[i]
dep[i]为从根节点得到
i
i
i节点的距离。
我们考虑如果从
i
i
i点出发的话那么如果它可以到达
j
j
j点那么
- d e p [ j ] − d e p [ i ] < = x [ j ] dep[j] - dep[i] <= x[j] dep[j]−dep[i]<=x[j]
然后移项可以得到
-
d
e
p
[
j
]
−
x
[
j
]
<
=
d
e
p
[
i
]
dep[j] - x[j] <= dep[i]
dep[j]−x[j]<=dep[i]
然后对于每个点 i i i我们可以求得有多少个子树的点满足上面的条件,然后我们通过dfs序可以得到 i i i点子树节点的范围,然后通过树状数组维护上面的条件即可得到答案。
注:我们在维护的时候,要对dep按照从小到大的顺序排序,然后通过Bit维护。并且结果不包含本身
a c c o d e : ac\ code: ac code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define g getchar()
#define met(a, b) memset(a, b, sizeof(a))
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define per(i, a, b) for(int i = a; i >= b; i--)
#define fi first
#define se second
const int maxn = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const int mod = 100003;
inline ll read() {
ll x = 0, f = 1;
char ch = g;
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = g;}
while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = g;}
return x;
}
struct Point {
ll d, id;
bool operator < (const Point & b) {
return d < b.d;
}
} point[maxn];
struct Edge {
ll to, next, w;
} edge[maxn];
ll dep[maxn], L[maxn], R[maxn], tot = 0, first[maxn], num = 0, x[maxn], ans[maxn], c[maxn], n;
bool vis[maxn];
void init() {
met(c, 0);
dep[1] = 0;
met(L, 0);
met(vis,false);
vis[1] = true;
met(R, 0);
met(first, -1);
tot = num = 0;
}
void addEdge(int u, int v, int w) {
edge[num].to = v;
edge[num].w = w;
edge[num].next = first[u];
first[u] = num++;
}
void dfs(int u) {
L[u] = ++tot;
for(int e = first[u]; ~e; e = edge[e].next) {
int v = edge[e].to;
if(!vis[v]) {
dep[v] = dep[u] + edge[e].w;
vis[v] = true;
dfs(v);
}
}
R[u] = tot;
}
ll lowbit(int x) {return x & (-x);}
void upd(ll pos, ll x) {
while(pos <= n) {
c[pos] += x;
pos += lowbit(pos);
}
}
ll query(int pos) {
ll res = 0;
while(pos > 0) {
res += c[pos];
pos -= lowbit(pos);
}
return res;
}
int main() {
#if(1)
freopen("car.in", "r", stdin);
#endif
ll T = read();
while(T--) {
init();
n = read();
ll u, v, w;
rep(i, 1, n) x[i] = read();
rep(i, 1, n - 1) {
u = read(), v = read(), w = read();
addEdge(u, v, w);
addEdge(v, u, w);
}
dfs(1);
rep(i, 1, n) {
point[i].d = dep[i] - x[i];
point[i].id = i;
}
rep(i, n + 1, 2 * n) {
point[i].d = dep[i - n];
point[i].id = i - n;
}
sort(point + 1, point + 1 + n);
sort(point + 1 + n, point + 2 * n + 1);
int j = 1;
rep(i, n + 1, 2 * n) {
while(point[j].d <= point[i].d && j <= n) {
upd(L[point[j].id], 1);
j++;
}
ans[point[i].id] = query(R[point[i].id]) - query(L[point[i].id]);
}
rep(i, 1, n) {
printf("%lld", ans[i]);
if(i != n) printf(" ");
else printf("\n");
}
}
return 0;
}