Gym

J. Whistle's New Car
time limit per test
15 seconds
memory limit per test
512 megabytes
input
car.in
output
standard output

Whistle has bought a new car, which has an infinite fuel tank capacity.

He discovered an irregular country since it has n cities and there are exactly n - 1 roads between them, of course, all cities are connected. He is so much clever, he realized that the country is like a rooted tree of n nodes and node 1 is the root. Each city i has only one filling station by which he can fill his car's fuel tank in no more than Xi liter. Whistle liked the country very much, and he wants to know what the most attractive city in the country is. The attractiveness of the city i is defined by how much it’s reachable from other cities, in other words the attractiveness of city is the number of cities j that satisfies these condition:

  • City j is in the subtree of city i (except for city i itself).
  • Whistle will start at city j and will only fill his car’s fuel tank with Xj liters and never fill it again until he reach city i.
  • Whistle should be able to reach city i with non-negative fuel.

He knows the length of every road and that 1 Km will take exactly 1 liter on any road.

As you know, Whistle is very clever, but he is not that good at programming, so he asked you to help him. He wants to know the attractiveness of each city, so that he can decide which city to live in.

Input

The first line of input contains one integer T, the number of test cases.

The next line contains one integer (1 ≤ n ≤ 500, 000), The number of cities in the country.

The next line contains n integers (1 ≤ Xi ≤ 1, 000, 000, 000).

Each one of the next n - 1 line contains three integers ABC (1 ≤ A, B ≤ n and 1 ≤ C ≤ 1, 000, 000, 000), that means there is a road between city A and city B of length C.

Output

For each test case, output a line containing n integers, the attractiveness of each city.

Example
input
1
4
5 10 5 10
1 2 100
2 3 5
3 4 5
output
0 2 1 0
Note

Large I/O files. Please consider using fast input/output methods.

设dis[i]表示从根节点1走到第 i个节点的路径长度。

那么任意的路径u-->v(前提是u是v的祖先,不然要用lca,这里不需要)可以表示为dis[v] - dis[u]

那么如果v能走回到u,则需要a[v] >= dis[v] - dis[u],即是dis[v] - a[v] <= dis[u],其中dis[v] - a[v]是一个确定值。

那么题意转换成,对于每一个节点u,有一个值dis[u],问其子树中,有多少个节点,满足dis[sonNode] - a[sonNode] <= dis[u]的。

这里可以用dfs序,然后用区间第k大的线段树或者分块、离线BIT之类的数据结构维护。

但是注意到dis[]是关于深度递增的,就是越走到下面,dis越大,也就是单调。

那么dfs的时候,用个vector记录一下路径长度和节点id。二分找到第一个祖先,使得满足dis[sonNode] - a[sonNode] <= dis[u]

那么可以知道ans[那个祖先节点 ---- 当前节点的爸爸],这条路径上的贡献都要加1

其实也就是打标记。

和一维差不多,L....R中加上1等价于sum[L] += 1, sum[R + 1] -= 1

这里一样,sum[当前节点的爸爸] += 1, sum[第一个满足的祖先的爸爸] -= 1

不能从上到下打标记,因为儿子数目不确定,而爸爸是确定的。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 500000 + 20;
struct Edge {
    int u, v, tonext, len;
}e[maxn * 2];
int first[maxn], num;
int a[maxn];
void addEdge(int u, int v, int w) {
    ++num;
    e[num].u = u, e[num].v = v, e[num].len = w;
    e[num].tonext = first[u];
    first[u] = num;
}
int ans[maxn];
vector< pair<LL, int> > vc;
int vis[maxn], DFN;
void dfs(int cur, LL nowLen, int fa) {
    ans[fa]++;
    int pos = lower_bound(vc.begin(), vc.end(), make_pair(nowLen - a[cur], 0)) - vc.begin();
    pos--; //去到第一个满足的的祖先的爸爸
    if (pos >= 0) {
        ans[vc[pos].second]--;
    }
    vc.push_back(make_pair(nowLen, cur));
    for (int i = first[cur]; i; i = e[i].tonext) {
        int v = e[i].v;
        if (v == fa) continue;
        dfs(v, nowLen + e[i].len, cur);
        ans[cur] += ans[v];
    }
    vc.pop_back();
}
void work() {
    num = 0;
    ++DFN;
    memset(first, false, sizeof first);
    memset(ans, 0, sizeof ans);
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) cin >> a[i];
    for (int i = 1; i <= n - 1; ++i) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        addEdge(u, v, w);
        addEdge(v, u, w);
    }
    dfs(1, 0, 0);
    for (int i = 1; i <= n; ++i) {
        printf("%d ", ans[i]);
    }
    printf("
");
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    freopen("car.in", "r", stdin);
    int t;
    scanf("%d", &t);
    while (t--) work();
    return 0;
}
原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6719030.html