zoukankan      html  css  js  c++  java
  • UVALive 5061 Lightning Energy Report --LCA

    题意:给一棵树,每次给u到v的路径上所有点加上一个值,最后输出每个点的权值(初始为0)

    解法:每次在u,v间加k时,只要让u,v点的权值加上k,u,v的LCA处减去k(因为LCA的子树中加了两个k),再在LCA的父亲(如果有的话)减k,免除对上面的影响。最后dfs一遍,ans[u] += ans[v] (v是u的所有儿子)即可。

    这里LCA用RMQ求的。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    using namespace std;
    #define N 100107
    
    int fa[N],ans[N];
    vector<int> G[N];
    int ati[N],f[N],bn,b[N],dp[N][32],ind;
    
    void dfs(int u,int fa) {
        for(int i=0;i<G[u].size();i++) {
            int v = G[u][i];
            if(v == fa) continue;
            dfs(v,u);
            ans[u] += ans[v];
        }
    }
    
    void init()
    {
        memset(ati,0,sizeof(ati));
        memset(f,0,sizeof(f));
        memset(b,0,sizeof(b));
        memset(dp,0,sizeof(dp));
        bn = ind = 0;
    }
    
    void dfs_2(int u,int father)
    {
        int tmp = ++ind;
        f[tmp] = u;
        b[++bn] = tmp;
        ati[u] = bn;
        for(int i=0;i<G[u].size();i++)
        {
            int v = G[u][i];
            if(v == father) continue;
            fa[v] = u;
            dfs_2(v,u);
            b[++bn]=tmp;
        }
    }
    
    void RMQ_init(int n)
    {
        for (int i=1; i<=n; i++)  dp[i][0]=b[i];
        int m=floor(log((double)n*1.0)/log((double)2.0));
        for (int j=1; j<=m; j++)
          for (int i=1; i<=n-(1<<j)+1; i++)
              dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
    }
    
    int RMQ(int l,int r)
    {
        int k=floor(log((double)r-l+1)/log(2.0));
        return min(dp[l][k],dp[r-(1<<k)+1][k]);
    }
    
    int LCA(int a,int b)
    {
        if (ati[a] > ati[b]) swap(a,b);
        return f[RMQ(ati[a],ati[b])];
    }
    
    int main()
    {
        int t,cs = 1,i,n,m,u,v,k;
        scanf("%d",&t);
        while(t--)
        {
            init();
            memset(G,0,sizeof(G));
            memset(ans,0,sizeof(ans));
            scanf("%d",&n);
            for(i=0;i<n-1;i++) {
                scanf("%d%d",&u,&v);
                G[u].push_back(v);
                G[v].push_back(u);
            }
            dfs_2(0,-1);
            RMQ_init(bn);
            scanf("%d",&m);
            while(m--) {
                scanf("%d%d%d",&u,&v,&k);
                int lca = LCA(u,v);
                ans[u] += k, ans[v] += k;
                ans[lca] -= k;
                if(lca != 0) ans[fa[lca]] -= k;
            }
            dfs(0,-1);
            printf("Case #%d:
    ",cs++);
            for(i=0;i<n;i++) printf("%d
    ",ans[i]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    1058
    light oj 1067 费马小定理求逆元
    HDU 1022
    贪心
    HDU 4994 博弈。
    HDU 5234 背包。
    CodeForces 327B 水题。
    vue的$nextTick使用总结,this.$refs为undefined的解决办法,element Ui的树形控件setCheckedKeys方法无法使用
    Object.assign的用法
    react + antd 实现打印功能(踩了不少坑)
  • 原文地址:https://www.cnblogs.com/whatbeg/p/4231392.html
Copyright © 2011-2022 走看看