题意:给出一棵根节点为1的树,执行m次修改操作,每次修改为a,b,c,表示a节点的子树中,距离a小于等于b的子节点的权值加上c,求m次操作后每个节点的权值

分析:用线段树维护每层节点的权值,然后dfs遍历这颗树,当前节点有操作时,把当前节点的深度到被修改的最大深度都加上c(实际上只有当前节点的子节点才加c),而回朔的时候再将这个区间减c,这样就避免了对非子节点的影响

AC代码(线段树的区间更新):

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=3e5+10;
ll f[maxn],nex[maxn*2],to[maxn*2],cnt,level[maxn],n,m;
ll ans[maxn],num[maxn*4],lazy[maxn*4];
vector<pair<ll,ll>>ve[maxn];
void add(int a,int b)
{
cnt++;
to[cnt]=b;
nex[cnt]=f[a];
f[a]=cnt;
}
void updata(int st,int en,int l,int r,int rt,ll x)
{
//cout<<l<<" "<<r<<endl;
if(st<=l&&en>=r)
{
num[rt]+=x*(r-l+1);
lazy[rt]+=x;
return ;
}
int mid=(l+r)/2;
if(lazy[rt])
{
lazy[rt*2]+=lazy[rt];
lazy[rt*2+1]+=lazy[rt];
num[rt*2]+=lazy[rt]*(mid-l+1);
num[rt*2+1]+=lazy[rt]*(r-mid);
lazy[rt]=0;
}
if(st<=mid)updata(st,en,l,mid,rt*2,x);
if(en>=mid+1)updata(st,en,mid+1,r,rt*2+1,x);
num[rt]=num[rt*2]+num[rt*2+1];
}
ll quer(int x,int l,int r,int rt)
{
int mid=(l+r)/2;
if(l==r)return num[rt];
if(lazy[rt])
{
lazy[rt*2]+=lazy[rt];
lazy[rt*2+1]+=lazy[rt];
num[rt*2]+=lazy[rt]*(mid-l+1);
num[rt*2+1]+=lazy[rt]*(r-mid);
lazy[rt]=0;
}
if(x<=(l+r)/2)return quer(x,l,(l+r)/2,rt*2);
else return quer(x,(l+r)/2+1,r,rt*2+1);
num[rt]=num[rt*2]+num[rt*2+1];
}
void getlevel(int x,int l)
{
level[x]=l;
for(int i=f[x]; i; i=nex[i])
{
int v=to[i];
if(!level[v])getlevel(v,l+1);
}
}
void dfs(int x,int pre)
{
for(int i=0; i<ve[x].size(); i++)
{
updata(level[x],level[x]+ve[x][i].first,1,n,1,ve[x][i].second);
}
ans[x]=quer(level[x],1,n,1);
for(int i=f[x]; i; i=nex[i])
{
int v=to[i];
if(v!=pre)
dfs(v,x);
}
for(int i=0; i<ve[x].size(); i++)
{
updata(level[x],level[x]+ve[x][i].first,1,n,1,-ve[x][i].second);
}
}
int main()
{
ios::sync_with_stdio(false); cin>>n;
for(int i=1; i<=n-1; i++)
{
int a,b;
cin>>a>>b;
add(a,b);
add(b,a);
}
getlevel(1,1);
cin>>m;
for(int i=1; i<=m; i++)
{
ll a,b,c;
cin>>a>>b>>c;
ve[a].push_back(make_pair(b,c));
} dfs(1,-1);
for(int i=1; i<=n; i++)
cout<<ans[i]<<" ";
cout<<endl;
return 0;
}

  

AC代码(树状数组的区间更新):

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=3e5+10;
ll f[maxn],nex[maxn*2],to[maxn*2],cnt,n,m;
ll ans[maxn],c1[maxn],c2[maxn];
vector<pair<int,ll>>ve[maxn];
void add1(int a,int b)
{
cnt++;
to[cnt]=b;
nex[cnt]=f[a];
f[a]=cnt;
}
void add(int x,ll y)
{
for(int i=x; i<=n; i+=(i&-i))c1[i]+=y,c2[i]+=y*x;
}
ll quer(int x)
{
ll res=0;
for(int i=x; i>0; i-=(i&-i))res+=((x+1)*c1[i]-c2[i]);
return res;
}
void in_add(int l,int r,ll x)
{
add(l,x);
add(r+1,-x);
}
void dfs(int x,int pre,int l)
{
for(int i=0; i<ve[x].size(); i++)
in_add(l,l+ve[x][i].first,ve[x][i].second);
ans[x]=quer(l)-quer(l-1);
for(int i=f[x]; i; i=nex[i])
{
int v=to[i];
if(v!=pre)
dfs(v,x,l+1);
}
for(int i=0; i<ve[x].size(); i++)
in_add(l,l+ve[x][i].first,-ve[x][i].second);
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1; i<=n-1; i++)
{
int a,b;
cin>>a>>b;
add1(a,b);
add1(b,a);
}
cin>>m;
for(int i=1; i<=m; i++)
{
ll a,b,c;
cin>>a>>b>>c;
ve[a].push_back(make_pair(b,c));
}
dfs(1,-1,1);
for(int i=1; i<=n; i++)
cout<<ans[i]<<" ";
cout<<endl;
return 0;
}

  

1076E - Vasya and a Tree(图的遍历)的更多相关文章

  1. Codeforces 1076E Vasya and a Tree(树状数组)或dfs

    题意:给你一颗以1为根节点的树,初始所有节点的权值为0,然后有m个操作,每个操作将点x的所有距离不超过d的节点权值+1,问经过m次操作后每个节点权值是多少? 思路:如果是一个序列,就可以直接用树状数组 ...

  2. CF 1076E Vasya and a Tree(线段树+树剖)

    传送门 解题思路 首先按照每个修改时\(x\)的深度\(+d\)从大到小排序,然后按照深度分层,一层一层的修改,修改的时候就直接暴力修改子树,然后每做完一层把答案都取下来,因为以后的所有修改的深度都小 ...

  3. codeforces 1076E Vasya and a Tree 【dfs+树状数组】

    题目:戳这里 题意:给定有n个点的一棵树,顶点1为根.m次操作,每次都把以v为根,深度dep以内的子树中所有的顶点(包括v本身)加x.求出最后每个点的值为多少. 解题思路:考虑到每次都只对点及其子树操 ...

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

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

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

    题面 Vasya has a tree consisting of n vertices with root in vertex 1. At first all vertices has 0 writ ...

  6. CodeForces-1076E Vasya and a Tree

    CodeForces - 1076E Problem Description: Vasya has a tree consisting of n vertices with root in verte ...

  7. 图的遍历(搜索)算法(深度优先算法DFS和广度优先算法BFS)

    图的遍历的定义: 从图的某个顶点出发访问遍图中所有顶点,且每个顶点仅被访问一次.(连通图与非连通图) 深度优先遍历(DFS): 1.访问指定的起始顶点: 2.若当前访问的顶点的邻接顶点有未被访问的,则 ...

  8. C++编程练习(9)----“图的存储结构以及图的遍历“(邻接矩阵、深度优先遍历、广度优先遍历)

    图的存储结构 1)邻接矩阵 用两个数组来表示图,一个一维数组存储图中顶点信息,一个二维数组(邻接矩阵)存储图中边或弧的信息. 2)邻接表 3)十字链表 4)邻接多重表 5)边集数组 本文只用代码实现用 ...

  9. Kruskal和prime算法的类实现,图的遍历BFS算法。

    一.图的遍历 #include<iostream> #include<queue> #include<vector> using namespace std; in ...

随机推荐

  1. [20181109]12c sqlplus rowprefetch参数5

    [20181109]12c sqlplus rowprefetch参数5.txt --//这几天一直在探究设置sqlplus参数rowprefetch与arraysize的关系,有必要做一些总结以及一 ...

  2. 大话C#之委托

    开篇先来扯下淡,上篇博客LZ在结尾说这篇博客会来说说C#中的事件.但是当LZ看完事件之后发现事件是以委托为基础来实现的,于是LZ就自作主张地在这篇博客中先来说说委托,还烦请各位看官见谅!!!另外关于委 ...

  3. Windows Server 2016-Powershell管理站点复制

    对于Active Directory的Windows PowerShell包括管理复制.网站.域和森林,域控制器以及分区的能力.例如Active Directory的站点和服务管理单元和repadmi ...

  4. mysql 数据库 命令行的操作——对表和字段的操作

    一.对表的操作 1.查看所有表 show tables: 2.创建表 create table 表名(字段1 类型1 约束1 ,字段2 类型2 约束2): 3.修改表的名字 rename table ...

  5. mysql中的升序和降序以及一个字段升序和一个字段降序

    mySql中,升序为asc,降序为desc.例如: 升序:select   *  from  表名 order by  表中的字段 asc(mysql中默认是升序排列,可不写) 降序:select   ...

  6. 设计模式のFlyweight(享元模式)----结构模式

    一.产生背景 享元模式:它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件:它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件.通常物件中的部分状态是可以分享.常见做 ...

  7. 这些Linux命令,让你的工作事半功倍!

    这些Linux命令,让你的工作事半功倍! 最近都在和Linux打交道,感觉还不错.我觉得Linux相比windows比较麻烦的就是很多东西都要用命令来控制,当然,这也是很多人喜欢linux的原因,比较 ...

  8. Druid、BoneCP、DBCP、C3P0等主流数据库对比

    关键功能 Druid BoneCP DBCP C3P0 Proxool JBoss LRU 是 否 是 否 是 是 PSCache 是 是 是 是 否 是 PSCache-Oracle-Optimiz ...

  9. 转://WITH AS and materialize hints

    WITH AS: 就是将一个子查询部分独立出来,有时候是为了提高SQL语句的可读性,有时候是为了提高SQL语句性能. 如果一个SQL语句中,某个表会被访问多次,而且每次访问的限制条件一样的话,就可以使 ...

  10. 转://使用insert插入大量数据的总结

    使用insert插入大量数据的个人经验总结在很多时候,我们会需要对一个表进行插入大量的数据,并且希望在尽可能短的时间内完成该工作,这里,和大家分享下我平时在做大量数据insert的一些经验. 前提:在 ...