J - Whistle's New Car Gym - 101147J[Bit]
阿新 • • 發佈:2018-11-07
題意:有一棵以1為root,n個節點的根樹,然後存在一個有n個數字的陣列x,詢問從i節點最多走 步可以最多到達幾個父親上的點,然後陣列n個數字,分別為從 出發可以最多到達幾個點。
題解:
首先我們定義
為從根節點得到
節點的距離。
我們考慮如果從
點出發的話那麼如果它可以到達
點那麼
然後移項可以得到
-
然後對於每個點 我們可以求得有多少個子樹的點滿足上面的條件,然後我們通過dfs序可以得到 點子樹節點的範圍,然後通過樹狀陣列維護上面的條件即可得到答案。
注:我們在維護的時候,要對dep按照從小到大的順序排序,然後通過Bit維護。並且結果不包含本身
#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;
}