传送门
题意就是给你一颗
n
n
n个点的树,一开始权值都是
0
0
0,然后
m
m
m个操作,每个操作对一个点
x
x
x的子树中到它距离不超过
d
d
d的点权都加上
v
a
l
val
val,问最后所有点的点权是多少
对于子树的修改可以用树剖+线段树做到,但是对于半个子树的修改很难做到,那就可以将修改操作排一下序,按照 d e p [ x ] + d dep[x]+d dep[x]+d从大到小排,这样的话当修改完了一层,后面的修改都不会修改到这一层,就可以先把这一层的答案记下来,每次只需要修改子树就好了
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define N 300005
#define LL long long
#define ls cur<<1
#define rs cur<<1|1
#define len(x) (node[x].r-node[x].l+1)
using namespace std;
inline int rd(){
int x=0,f=1;char c=' ';
while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
return x*f;
}
int n,cnt,head[N],to[N<<1],nxt[N<<1],m;
LL ans[N];
int dep[N],dfn[N],rk[N],son[N],top[N],fa[N],siz[N],num;
vector<int> vec[N];
inline void add(int x,int y){to[++cnt]=y;nxt[cnt]=head[x];head[x]=cnt;}
struct QWQ{
int x,d,val;
bool operator <(const QWQ &y) const{
return dep[x]+d>dep[y.x]+y.d;
}
}a[N];
void dfs1(int u,int fat){
siz[u]=1; int maxson=-1;
for(int i=head[u];i;i=nxt[i]){
int v=to[i]; if(v==fat) continue;
dep[v]=dep[u]+1; fa[v]=u; vec[dep[v]].push_back(v);
dfs1(v,u); siz[u]+=siz[v];
if(maxson<siz[v]) maxson=siz[v],son[u]=v;
} return;
}
void dfs2(int u,int t){
dfn[u]=++num; rk[num]=u; top[u]=t;
if(!son[u]) return ;
dfs2(son[u],t);
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(!dfn[v]) dfs2(v,v);
}
}
struct Node{
LL sum,lazy; int l,r;
}node[N<<2];
inline void pushup(int cur){node[cur].sum=node[ls].sum+node[rs].sum;}
inline void pushdown(int cur){
if(!node[cur].lazy) return;
LL t=node[cur].lazy; node[cur].lazy=0;
node[ls].sum+=1LL*len(ls)*t; node[ls].lazy+=t;
node[rs].sum+=1LL*len(rs)*t; node[rs].lazy+=t;
}
void build(int cur,int L,int R){
if(L==R){
node[cur].l=node[cur].r=L;
return;
}
int mid=(L+R)>>1;
build(ls,L,mid); build(rs,mid+1,R);
node[cur].l=node[ls].l; node[cur].r=node[rs].r;
}
void update(int cur,int L,int R,int c){
if(L<=node[cur].l && node[cur].r<=R){
node[cur].sum+=1LL*len(cur)*c; node[cur].lazy+=c;
return;
}
pushdown(cur);
int mid=(node[cur].l+node[cur].r)>>1;
if(L<=mid) update(ls,L,R,c);
if(mid<R) update(rs,L,R,c);
pushup(cur);
}
LL query(int cur,int L,int R){
if(L<=node[cur].l && node[cur].r<=R) return node[cur].sum;
pushdown(cur);
int mid=(node[cur].l+node[cur].r)>>1; LL res=0;
if(L<=mid) res+=query(ls,L,R);
if(mid<R) res+=query(rs,L,R);
return res;
}
int main(){
n=rd();
for(int i=1;i<n;i++){
int x=rd(),y=rd();
add(x,y); add(y,x);
}
m=rd();
for(int i=1;i<=m;i++){
a[i].x=rd(),a[i].d=rd(),a[i].val=rd();
}
dep[1]=1; vec[1].push_back(1); dfs1(1,0); dfs2(1,1); build(1,1,n);
sort(a+1,a+m+1); int mx=0,pre;
for(int i=1;i<=n;i++) mx=max(mx,dep[i]); pre=mx;
for(int i=1;i<=m;i++){
int now=dep[a[i].x]+a[i].d;
while(pre>now) {
for(int j=0;j<vec[pre].size();j++){
int u=vec[pre][j]; ans[u]=query(1,dfn[u],dfn[u]);
} pre--;
}
update(1,dfn[a[i].x],dfn[a[i].x]+siz[a[i].x]-1,a[i].val);
}
while(pre>=1){
for(int j=0;j<vec[pre].size();j++){
int u=vec[pre][j]; ans[u]=query(1,dfn[u],dfn[u]);
} pre--;
}
for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
return 0;
}