J - Whistle's New Car Gym - 101147J[Bit]

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38081836/article/details/83753212

题意:有一棵以1为root,n个节点的根树,然后存在一个有n个数字的数组x,询问从i节点最多走 x [ i ] x[i] 步可以最多到达几个父亲上的点,然后数组n个数字,分别为从 1 , 2 , n 1, 2, \dots n 出发可以最多到达几个点。


题解:
首先我们定义 d e p [ i ] dep[i] 为从根节点得到 i i 节点的距离。
我们考虑如果从 i i 点出发的话那么如果它可以到达 j j 点那么

  • d e p [ j ] d e p [ 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]
    然后对于每个点 i i 我们可以求得有多少个子树的点满足上面的条件,然后我们通过dfs序可以得到 i i 点子树节点的范围,然后通过树状数组维护上面的条件即可得到答案。
    注:我们在维护的时候,要对dep按照从小到大的顺序排序,然后通过Bit维护。并且结果不包含本身

a c   c o d e : 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;
}

猜你喜欢

转载自blog.csdn.net/m0_38081836/article/details/83753212
今日推荐