제출 #1199481

#제출 시각아이디문제언어결과실행 시간메모리
1199481woohyun_jngTransport (COCI19_transport)C++20
0 / 100
0 ms0 KiB
#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef array<int, 2> pr;

const int MAX = 100001;

vector<pr> adj[MAX];
vector<int> comp;

int sz[MAX], A[MAX], ans, tree[MAX * 8], S;
bool chk[MAX];

int get_sz(int node, int par) {
    sz[node] = 1;
    for (pr i : adj[node]) {
        if (i[0] == par || chk[i[0]])
            continue;
        sz[node] += get_sz(i[0], node);
    }
    return sz[node];
}

int get_cent(int node, int par, int cap) {
    for (pr i : adj[node]) {
        if (i[0] == par || chk[i[0]])
            continue;
        if (sz[i[0]] * 2 > cap)
            return get_cent(i[0], node, cap);
    }
    return node;
}

int query(int n, int s, int e, int l, int r) {
    if (r < s || e < l)
        return 0;
    else if (l <= s && e <= r)
        return tree[n];
    else {
        int m = s + e >> 1;
        return query(n << 1, s, m, l, r) + query(n << 1 | 1, m + 1, e, l, r);
    }
}

void update(int n, int s, int e, int idx, int v) {
    if (idx < s || e < idx)
        return;
    else if (s == e)
        tree[n] += v;
    else {
        int m = s + e >> 1;
        update(n << 1, s, m, idx, v), update(n << 1 | 1, m + 1, e, idx, v);
        tree[n] = tree[n << 1] + tree[n << 1 | 1];
    }
}

int query(int n) {
    n = lower_bound(comp.begin(), comp.end(), n) - comp.begin() + 1;
    return query(1, 1, S, 1, n);
}

void update(int n, int v) {
    n = lower_bound(comp.begin(), comp.end(), n) - comp.begin() + 1;
    update(1, 1, S, n, v);
}

void dfs0(int node, int par, int val, int mn) {
    comp.push_back(-val);
    if (A[node] + mn >= 0)
        comp.push_back(A[node] + mn);

    for (pr i : adj[node]) {
        if (i[0] == par || chk[i[0]])
            continue;
        dfs0(i[0], node, min(val, val + A[node] - i[1]), min(0ll, mn + A[node]) - i[1]);
    }
}

void dfs1(int node, int par, int val) {
    update(-val, 1);

    for (pr i : adj[node]) {
        if (i[0] == par || chk[i[0]])
            continue;
        dfs1(i[0], node, min(val, val + A[node] - i[1]));
    }
}

void dfs2(int node, int par, int mn) {
    if (A[node] + mn >= 0)
        ans += query(A[node] + mn);

    for (pr i : adj[node]) {
        if (i[0] == par || chk[i[0]])
            continue;
        dfs2(i[0], node, min(0ll, mn + A[node]) - i[1]);
    }
}

void dfs3(int node, int par, int val) {
    update(-val, -1);

    for (pr i : adj[node]) {
        if (i[0] == par || chk[i[0]])
            continue;
        dfs3(i[0], node, min(val, val + A[node] - i[1]));
    }
}

void dnc(int node) {
    int cent = get_cent(node, -1, get_sz(node, -1));
    chk[cent] = true, comp.clear();

    comp.push_back(0);
    for (pr i : adj[cent]) {
        if (chk[i[0]])
            continue;
        dfs0(i[0], cent, A[cent] - i[1], -i[1]);
    }

    sort(comp.begin(), comp.end()), comp.erase(unique(comp.begin(), comp.end()), comp.end()), S = comp.size();

    update(0, 1);
    for (pr i : adj[cent]) {
        if (chk[i[0]])
            continue;
        dfs1(i[0], cent, A[cent] - i[1]);
    }

    ans += query(0);
    for (pr i : adj[cent]) {
        if (chk[i[0]])
            continue;
        dfs3(i[0], cent, A[cent] - i[1]);
        dfs2(i[0], cent, -i[1]);
        dfs1(i[0], cent, A[cent] - i[1]);
    }

    update(0, -1);
    for (pr i : adj[cent]) {
        if (chk[i[0]])
            continue;
        dfs3(i[0], cent, A[cent] - i[1]);
    }

    for (pr i : adj[cent]) {
        if (chk[i[0]])
            continue;
        dnc(i[0]);
    }
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    int N, X, Y, Z;

    cin >> N;
    for (int i = 1; i <= N; i++)
        cin >> A[i];

    for (int i = 1; i < N; i++) {
        cin >> X >> Y >> Z;
        adj[X].push_back({Y, Z}), adj[Y].push_back({X, Z});
    }

    dnc(1);

    ans -= N;
    cout << ans << '\n';

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...