I - Vasya and a Tree

CodeForces - 1076E

其实参考完别人的思路,写完程序交上去,还是没理解啥意思。。昨晚再仔细想了想。终于弄明白了(有可能不对

题意是有一棵树n个点,初始时候每个点权值都为0,m次修改,对v的叶子节点且距离小于d的都加上x

也就是v以下d层包括v自身都加上x 问最后每个点的权值

现在一想 用线段树来维护就是很自然的事了

但是要维护什么值呢

维护的就是某个深度上增加的值

先更新 后回溯取消更新

详见代码注释

#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#define lp p<<1
#define rp p<<1|1
#define ll long long
using namespace std;
const int maxn = 3e5 + ;
typedef pair<int, int> P;
int n, m;
int tot, head[maxn];
struct Edge{ int to, next; }edge[maxn<<];
vector<P> vec[maxn];
ll a[maxn<<], lazy[maxn<<], res[maxn];
inline void addedge(int u, int v) {
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
inline void pushup(int p) {
a[p] = a[lp] + a[rp];
}
inline void pushdown(int p, int llen, int rlen) {
if (lazy[p]) {
lazy[lp] += lazy[p];
lazy[rp] += lazy[p];
a[lp] += lazy[p] * llen;
a[rp] += lazy[p] * rlen;
lazy[p] = ;
}
}
void build(int p, int l, int r) {
a[p] = lazy[p] = ;
if (l == r) return;
int mid = l + r >> ;
build(lp, l, mid);
build(rp, mid + , r);
pushup(p);
}
void update(int p, int l, int r, int x, int y, int z) {
if (x <= l && y >= r) {
a[p] += 1LL * z * (r - l + );
lazy[p] += z;
return;
}
int mid = l + r >> ;
pushdown(p, mid - l + , r - mid);
if (x <= mid) update(lp, l, mid, x, y, z);
if (y > mid) update(rp, mid + , r, x, y, z);
pushup(p);
}
ll query(int p, int l, int r, int u) {
if (l == r) return a[p];
int mid = l + r >> ;
pushdown(p, mid - l + , r - mid);
if (u <= mid) return query(lp, l, mid, u);
return query(rp, mid + , r, u);
}
//截至这里 应该都是线段树的基本操作 没啥好说的
void dfs(int f, int u, int d) {
for (int i = , sz = vec[u].size(); i < sz; i++) {
// 因为线段树记录的是深度 所以就可以把当前结点以及深度差为k的全部更新一遍
update(, , n, d, min(n, d + vec[u][i].first), vec[u][i].second);
}
//接下来dfs遍历的时候的update操作不会影响到父节点了 所以可以直接query得到答案
res[u] = query(, , n, d);
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (v == f) continue;
// 深度位置是共享的 比如 1既连接2又连接3 上面更新了深度为1,2的 在线段树上 2代表的就是2和3的权值
dfs(u, v, d + );
}
for (int i = ; i < vec[u].size(); i++) {
//回溯取消标记
update(, , n, d, min(n, d + vec[u][i].first), -vec[u][i].second);
}
}
int main() {
scanf("%d", &n);
tot = ;
memset(head, -, sizeof(head));
for (int i = , u, v; i < n - ; i++) {
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
scanf("%d", &m);
while (m--) {
int v, d, x;
scanf("%d%d%d", &v, &d, &x);
vec[v].push_back(make_pair(d, x));
}
dfs(-, , );
for (int i = ; i <= n; i++) {
printf("%I64d", res[i]);
if (i == n) puts("");
else putchar(' ');
}
return ;
}

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

  1. 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 ...

  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. Item 17: 理解特殊成员函数的生成规则

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 C++的官方说法中,特殊成员函数是C++愿意去主动生成的.C++9 ...

  2. LeetCode 832. Flipping an Image

    Given a binary matrix A, we want to flip the image horizontally, then invert it, and return the resu ...

  3. OM1、OM2、OM3和OM4光纤之间的区别

    “OM”stand for optical multi-mode,即光模式,是多模光纤表示光纤等级的标准.不同等级传输时的带宽和最大距离不同,从以下几个方面分析它们之间的区别.  一.OM1.OM2. ...

  4. 软件工程练习:模块化,单元测试,回归测试,TDD

    这是<构建之法>实战教学的一部分.适合作为同学们的第二个程序作业. 第一个程序作业: 请看 “概论” 一章的练习,或者老师的题目,例如这个. 作业要求: 软件工程的作业越来越有意思了, 我 ...

  5. stark组件的增删改(新)

      1.效果图 2.详细步骤解析 3.总结.代码   1.效果图 增 删除 改 2.详细步骤解析 1.构造增删改查url,反向解析 2.ModelForm定制add.edit页面 3.starak中的 ...

  6. Java面试题详解二:java中的关键字

    一,final1.被final修饰的类不可以被继承2.被final修饰的方法不可以被重写3.被final修饰的变量不可以被改变  重点就是第三句.被final修饰的变量不可以被改变,什么不可以被改变呢 ...

  7. Webbench、ab命令:做压力测试的工具和性能的监控工具

    DDOS攻击:???DDOS概述:分布式拒绝服务(DDoS:Distributed Denial of Service)攻击,指借助于客户/服务器技术,将多个计算机联合起来作为攻击平台,对一个或多个目 ...

  8. 【Python3练习题 002】企业发放的奖金根据利润提成

    # [Python练习题 002]企业发放的奖金根据利润提成.# 利润(I)低于或等于10万元时,奖金可提10%:利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分, ...

  9. Oracle 表空间不足引起的问题及解决方法

    -- 1 向数据库导入数据时报了ORA-01653: unable to extend table错误,网上查了下原因是由于表空间不足引起的: 查询表空间使用情况语句 select a.tablesp ...

  10. 通过 MySQL 存储原理来分析排序和锁(转)

    先抛出几个问题 为什么不建议使用订单号作为主键? 为什么要在需要排序的字段上加索引? for update 的记录不存在会导致锁住全表? redolog 和 binlog 有什么区别? MySQL 如 ...