题面

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;
}

Vasya and a Tree CodeForces - 1076E (线段树 + dfs)的更多相关文章

  1. Vasya and a Tree CodeForces - 1076E(线段树+dfs)

    I - Vasya and a Tree CodeForces - 1076E 其实参考完别人的思路,写完程序交上去,还是没理解啥意思..昨晚再仔细想了想.终于弄明白了(有可能不对 题意是有一棵树n个 ...

  2. S - Query on a tree HDU - 3804 线段树+dfs序

    S - Query on a tree HDU - 3804   离散化+权值线段树 题目大意:给你一棵树,让你求这棵树上询问的点到根节点直接最大小于等于val的长度. 这个题目和之前写的那个给你一棵 ...

  3. Z - New Year Tree CodeForces - 620E 线段树 区间种类 bitset

    Z - New Year Tree CodeForces - 620E 这个题目还没有写,先想想思路,我觉得这个题目应该可以用bitset, 首先这个肯定是用dfs序把这个树转化成线段树,也就是二叉树 ...

  4. Alyona and a tree CodeForces - 739B (线段树合并)

    大意: 给定有根树, 每个点$x$有权值$a_x$, 对于每个点$x$, 求出$x$子树内所有点$y$, 需要满足$dist(x,y)<=a_y$. 刚开始想错了, 直接打线段树合并了..... ...

  5. Vasya and a Tree CodeForces - 1076E

    很好的思维 转化为对树上的深度差分 回朔的思想 对查询离线 #include<iostream> #include<cstdio> #include<cmath> ...

  6. Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论

    Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论 题意 给你一段数,然后小明去猜某一区间内的gcd,这里不一定是准确值,如果在这个区间内改变 ...

  7. 2016湖南省赛 I Tree Intersection(线段树合并,树链剖分)

    2016湖南省赛 I Tree Intersection(线段树合并,树链剖分) 传送门:https://ac.nowcoder.com/acm/contest/1112/I 题意: 给你一个n个结点 ...

  8. CF620E New Year Tree 状压+线段树(+dfs序?)

    借用学长的活:60种颜色是突破口(我咋不知道QAQ) 好像这几道都是线段树+dfs序??于是你可以把60种颜色压进一个long long 里,然后向上合并的时候与一下(太妙了~) 所以记得开long ...

  9. HDU 5692 线段树+dfs序

    Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

随机推荐

  1. quarts之Cron表达式示例

    cron表达式含义及范例如下: 字段名                 允许的值                        允许的特殊字符 秒                         0- ...

  2. iOS viewDidLayoutSubviews,viewdidload

    由于种种原因,最近才开始真正在新项目中使用autolayout,使用过程中虽说是比较顺畅,但是也遇到了一些麻烦,比如: 我使用的XIB默认是4寸屏幕,我再XIB中增加一个viewA,宽度为320,约束 ...

  3. Facebook POP动效库使用教程

    编者注:用Origami作iOS动效的同学如果愁怎么实现,可以把这个给开发看看作为参考哦 如果说Origami这款动效原型工具是Facebook Paper的幕后功臣,那么POP便是Origami的地 ...

  4. 2019-8-31-msbuild-项目文件常用判断条件

    title author date CreateTime categories msbuild 项目文件常用判断条件 lindexi 2019-08-31 16:55:59 +0800 2019-7- ...

  5. 《mysql必知必会》笔记3(插入、更新、删除、创建删除更新表、视图)

    十九:插入数据 1:insert语句用来将行插入数据表中,可以插入完整的行.行的一部分.插入多行.插入某些查询的结果. 2:不指定列名,可以这样插入: insert into customers va ...

  6. MaxCompute SQL 使用正则表达式选列

    编辑MaxCompute SQL 时,经常会需要在某个表N个列中指定一些列.若需要指定的列比较少,编写SQL时一个个输入既可.当遇到列多的时候,一个个输入就会非常费劲.本文将介绍如何在编写MaxCom ...

  7. 阿里云oss上传图片报错,The OSS Access Key Id you provided does not exist in our records.解决方法

    vue项目 1.安装OSS的Node SDK npm install ali-oss --save 2.参考官方提示https://help.aliyun.com/document_detail/11 ...

  8. HDU 5672 String【尺取法】

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5672 题意: 有一个10≤长度≤1,000,000的字符串,仅由小写字母构成.求有多少个子串,包含有 ...

  9. Istio on ACK集成生态(2): 扩展AlertManager集成钉钉助力可观测性监控能力

    阿里云容器服务Kubernetes(简称ACK)支持一键部署Istio,可以参考文档在ACK上部署使用Isito.Istio on ACK提供了丰富的监控能力,为网格中的服务收集遥测数据,其中Mixe ...

  10. 模板—堆优化dijkstra

    ];]; void dijkstra(int s) { memset(dis,0x7f,sizeof(dis));ma(v); priority_queue<pair<int,int> ...