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:\n",cs++);

        for(i=0;i<n;i++) printf("%d\n",ans[i]);

    }

    return 0;

}
View Code

 

你可能感兴趣的:(port)