Codeforces Contest 1076 problem E Vasya and a Tree —— dfs+树状数组

Vasya has a tree consisting of n vertices with root in vertex 1. At first all vertices has 0 written on it.

Let d(i,j) be the distance between vertices i and j, i.e. number of edges in the shortest path from i to j. Also, let’s denote k-subtree of vertex x — set of vertices y such that next two conditions are met:

x is the ancestor of y (each vertex is the ancestor of itself);
d(x,y)≤k.
Vasya needs you to process m queries. The i-th query is a triple vi, di and xi. For each query Vasya adds value xi to each vertex from di-subtree of vi.

Report to Vasya all values, written on vertices of the tree after processing all queries.

Input
The first line contains single integer n (1≤n≤3⋅105) — number of vertices in the tree.

Each of next n−1 lines contains two integers x and y (1≤x,y≤n) — edge between vertices x and y. It is guarantied that given graph is a tree.

Next line contains single integer m (1≤m≤3⋅105) — number of queries.

Each of next m lines contains three integers vi, di, xi (1≤vi≤n, 0≤di≤109, 1≤xi≤109) — description of the i-th query.

Output
Print n integers. The i-th integers is the value, written in the i-th vertex after processing all queries.

Examples
inputCopy
5
1 2
1 3
2 4
2 5
3
1 1 1
2 0 10
4 10 100
outputCopy
1 11 1 100 0
inputCopy
5
2 3
2 1
5 4
3 4
5
2 0 4
3 10 1
1 2 3
2 3 10
1 1 7
outputCopy
10 24 14 11 11
Note
In the first exapmle initial values in vertices are 0,0,0,0,0. After the first query values will be equal to 1,1,1,0,0. After the second query values will be equal to 1,11,1,0,0. After the third query values will be equal to 1,11,1,100,0.

题意:

给你一棵树,以1为根,给你一些操作x y z:x的子树深度不超过y的所有子节点的值+z,一开始所有节点的值为0,问你最后所有节点的值是多少。

题解:

存储每个点有多少修改,然后向下dfs的时候以深度为x轴,值为y轴做树状数组,结束的时候删掉。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pa pair<int,ll>
const int N=3e5+5;
vector<pa>vec[N];
ll ans[N],sum[N];
struct node
{
    int to,next;
}e[N*2];
int cnt,head[N];
void add(int x,int y)
{
    e[cnt].to=y;
    e[cnt].next=head[x];
    head[x]=cnt++;
}
int lowbit(int x)
{
    return x&(-x);
}
void add(int x,ll val)
{
    for(int i=x;i<N;i+=lowbit(i))
        sum[i]+=val;
}
ll query(int x)
{
    ll ans=0;
    for(int i=x;i;i-=lowbit(i))
        ans+=sum[i];
    return ans;
}
void dfs(int x,int fa,int dep)
{
    for(int i=0;i<vec[x].size();i++)
        add(dep,vec[x][i].second),add(dep+vec[x][i].first+1,-vec[x][i].second),ans[x]+=vec[x][i].second;
    for(int i=head[x];~i;i=e[i].next)
    {
        int ne=e[i].to;
        if(ne==fa)
            continue;
        ans[ne]+=query(dep+1);
        dfs(ne,x,dep+1);
    }
    for(int i=0;i<vec[x].size();i++)
        add(dep,-vec[x][i].second),add(dep+vec[x][i].first+1,vec[x][i].second);
}
int main()
{
    memset(head,-1,sizeof(head));
    int n,m;
    int x,y;
    ll w;
    scanf("%d",&n);
    for(int i=1;i<n;i++)
        scanf("%d%d",&x,&y),add(x,y),add(y,x);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
        scanf("%d%d%lld",&x,&y,&w),vec[x].push_back({y,w});
    dfs(1,0,1);
    for(int i=1;i<=n;i++)
        printf("%lld%c",ans[i],i==n?'\n':' ');
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值