zoukankan      html  css  js  c++  java
  • GYM

    题意:

      给出一颗有点权和边权的树。求每一个点u的子树中有多少点v,使得点v到点u的距离小于等于点v的权值。

    题解:

      对于每一个点,倍增的预处理出他的祖宗节点及距离。根据预处理的结果求出每个点能到的最远的祖宗节点。

      设点u能到的最远祖宗节点为v。利用差分的思想在点tree[u]+1,点tree[v]-1。

      最后每个点的答案就是子树的tree[]和。

    #include <bits/stdc++.h> 
    using namespace std;
    typedef long long ll;
    const int maxn = 5e5+10;
    int t, n, u, v, tree[maxn], ans[maxn];
    ll c, x[maxn];
    struct node {
        ll val; int nod;
    };
    node fa[32][maxn], tmp;
    vector<node> g[maxn];
    void dfs(int u, int pre) {
        fa[0][u].nod = pre;
        int len = g[u].size();
        for(int i = 0; i < len; i++) {
            int v = g[u][i].nod;
            if(v==pre) {
                fa[0][u].val = g[u][i].val;
                continue;
            }
            dfs(v, u);
        }
    }
    void dfs_double(int u, int pre) {
        int len = g[u].size();
        for(int i = 0; i < len; i++) {
            int v = g[u][i].nod;
            if(v==pre) continue;
            dfs_double(v, u);
        }
        tree[u]++;
        ll tv = x[u];
        for(int k = 31; k >= 0; k--) {
            if(fa[k][u].val <= tv) {
                tv -= fa[k][u].val;
                u = fa[k][u].nod;
            }
        }
        tree[u]--;
    }
    void solve(int u, int pre) {
        int len = g[u].size();
        for(int i = 0; i < len; i++) {
            int v = g[u][i].nod;
            if(v==pre) continue;
            solve(v, u);
        }
        for(int i = 0; i < len; i++) {
            int v = g[u][i].nod;
            if(v==pre) continue;
            ans[u] += tree[v]+ans[v];
        }
    }
    int main() {
        freopen("car.in","r",stdin);
        scanf("%d", &t);
        while(t--) {
            scanf("%d", &n);
            memset(tree, 0, sizeof(tree));
            memset(ans, 0, sizeof(ans));
            for(int i = 1; i <= n; i++) g[i].clear();
            for(int i = 1; i <= n; i++) scanf("%lld", &x[i]);
            for(int i = 1; i < n; i++) {
                scanf("%d%d%lld", &u, &v, &tmp.val);
                tmp.nod = v;
                g[u].push_back(tmp);
                tmp.nod = u;
                g[v].push_back(tmp);
            }
            dfs(1, 1);
            for(int k = 0; k < 31; k++) {
                for(int v = 1; v <= n; v++) { 
                    fa[k+1][v].nod = fa[k][fa[k][v].nod].nod;
                    fa[k+1][v].val = fa[k][v].val+fa[k][fa[k][v].nod].val;
                }
            }
            dfs_double(1, 0);
            solve(1, 0);
            for(int i = 1; i <= n; i++) {
                printf("%d", ans[i]);
                if(i==n) puts("");
                else printf(" ");
            }
        }
    }
    View Code
  • 相关阅读:
    海康SDK/大华SDK协议视频智能分析平台EasyCVR播放器界面滚动条属性优化分享
    TSINGSEE青犀视频EasyCVR视频融合共享平台兼容性再扩展,大华SDK轻松接入
    海康SDK/大华SDK安防视频智能分析平台EasyCVR如何将通道视频流推送至CDN分发?
    迭代器和生成器
    内置函数
    递归函数
    函数进阶------闭包函数
    装饰器
    函数
    经典100厘
  • 原文地址:https://www.cnblogs.com/Pneuis/p/8901123.html
Copyright © 2011-2022 走看看