Vasya and a Tree CodeForces

题面
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:
题意
在一棵树上,进行m次操作,每次将结点v的子树上,且与v距离小于等于d的结点加上权值加上x.
所有操作结束之后,输出每一点的权值.
思路
在字树上,同一层结点,与树上根结点的距离都是相等的.
首先,我们预处理每个结点当了那些操作的根节点.
dfs遍历到这些节点时,把dep[u]~dep[u]+d的区间加上x
之后查询ans[u],ans[u]就等于dep[u]的权值
回溯时再减去x.

#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>

#define fuck(x) cerr<<#x<<" = "<<x<<endl;
#define debug(a, x) cerr<<#a<<"["<<x<<"] = "<<a[x]<<endl;
#define lson l,mid,ls
#define rson mid+1,r,rs
#define ls (rt<<1)
#define rs ((rt<<1)|1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int loveisblue = 486;
const int maxn = 300086;
const int maxm = 600086;
const int inf = 0x3f3f3f3f;
const ll Inf = 999999999999999999;
const int mod = 1000000007;
const double eps = 1e-6;
const double pi = acos(-1);

int dep[maxn];

int Head[maxn],cnt;
struct edge{
    int Next,v;
}e[maxm];
void add_edge(int u,int v){
    e[cnt].Next=Head[u];
    e[cnt].v=v;
    Head[u]=cnt++;
}

ll ans[maxn];

ll sum[maxn<<2],lazy[maxn<<2];

void push_down(int l,int r,int rt){
    int mid = (l+r)>>1;
    ll len1 = mid-l+1;
    ll len2 = r-mid;

    sum[ls]+=len1*lazy[rt];
    sum[rs]+=len2*lazy[rt];
    lazy[ls]+=lazy[rt];
    lazy[rs]+=lazy[rt];
    lazy[rt]=0;
}

void update(int l,int r,int rt,int L,int R,int val){
    if(L<=l&&R>=r){
        sum[rt]+=1ll*(r-l+1)*val;
        lazy[rt]+=val;
        return;
    }
    if(lazy[rt]){push_down(l,r,rt);}
    int mid = (l+r)>>1;
    if(L<=mid)update(lson,L,R,val);
    if(R>mid){update(rson,L,R,val);}
}

ll query(int l,int r,int rt,int pos){

    if(l==r){
        return sum[rt];
    }
    if(lazy[rt]){push_down(l,r,rt);}
    int mid = (l+r)>>1;
    if(pos<=mid){
        return query(lson,pos);
    }else{
        return query(rson,pos);
    }

}
int mx=0;
struct node{
    int d,x;
};

vector<node>vec[maxn];
void dfs(int u,int fa,int d){
    dep[u]=d;
    for(int k=Head[u];k!=-1;k=e[k].Next){
        int v=e[k].v;
        if(v==fa){ continue;}
        dfs(e[k].v,u,d+1);
    }
    mx=max(mx,d);
}

void dfs1(int u,int fa){
    int siz =vec[u].size();
    for(int i=0;i<siz;i++) {
        update(1, mx, 1, dep[u], min(dep[u] + vec[u][i].d,mx),vec[u][i].x);
    }
    ans[u]+=query(1,mx,1,dep[u]);
    for(int k=Head[u];k!=-1;k=e[k].Next){
        int v=e[k].v;
        if(v==fa){ continue;}
        dfs1(e[k].v,u);
    }

    for(int i=0;i<siz;i++) {
        update(1, mx, 1, dep[u], min(dep[u] + vec[u][i].d,mx),-vec[u][i].x);
    }

}



int main() {
    ios::sync_with_stdio(true);
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif


    memset(Head,-1,sizeof(Head));
    int n;
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add_edge(x,y);
        add_edge(y,x);
    }

    int m;
    scanf("%d",&m);
    dfs(1,0,1);
    for(int i=1;i<=m;i++){
        int v,d,x;
        scanf("%d%d%d",&v,&d,&x);
        vec[v].push_back({d,x});
    }

    dfs1(1,0);


    for(int i=1;i<=n;i++){
        printf("%lld ",ans[i]);
    }


    return 0;
}

原文地址:https://www.cnblogs.com/ZGQblogs/p/11474298.html