I - Vasya and a Tree

CodeForces - 1076E

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

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

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

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

但是要维护什么值呢

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

先更新 后回溯取消更新

详见代码注释

  1. #include <cstdio>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <cstring>
  5. #define lp p<<1
  6. #define rp p<<1|1
  7. #define ll long long
  8. using namespace std;
  9. const int maxn = 3e5 + ;
  10. typedef pair<int, int> P;
  11. int n, m;
  12. int tot, head[maxn];
  13. struct Edge{ int to, next; }edge[maxn<<];
  14. vector<P> vec[maxn];
  15. ll a[maxn<<], lazy[maxn<<], res[maxn];
  16. inline void addedge(int u, int v) {
  17. edge[tot].to = v;
  18. edge[tot].next = head[u];
  19. head[u] = tot++;
  20. }
  21. inline void pushup(int p) {
  22. a[p] = a[lp] + a[rp];
  23. }
  24. inline void pushdown(int p, int llen, int rlen) {
  25. if (lazy[p]) {
  26. lazy[lp] += lazy[p];
  27. lazy[rp] += lazy[p];
  28. a[lp] += lazy[p] * llen;
  29. a[rp] += lazy[p] * rlen;
  30. lazy[p] = ;
  31. }
  32. }
  33. void build(int p, int l, int r) {
  34. a[p] = lazy[p] = ;
  35. if (l == r) return;
  36. int mid = l + r >> ;
  37. build(lp, l, mid);
  38. build(rp, mid + , r);
  39. pushup(p);
  40. }
  41. void update(int p, int l, int r, int x, int y, int z) {
  42. if (x <= l && y >= r) {
  43. a[p] += 1LL * z * (r - l + );
  44. lazy[p] += z;
  45. return;
  46. }
  47. int mid = l + r >> ;
  48. pushdown(p, mid - l + , r - mid);
  49. if (x <= mid) update(lp, l, mid, x, y, z);
  50. if (y > mid) update(rp, mid + , r, x, y, z);
  51. pushup(p);
  52. }
  53. ll query(int p, int l, int r, int u) {
  54. if (l == r) return a[p];
  55. int mid = l + r >> ;
  56. pushdown(p, mid - l + , r - mid);
  57. if (u <= mid) return query(lp, l, mid, u);
  58. return query(rp, mid + , r, u);
  59. }
  60. //截至这里 应该都是线段树的基本操作 没啥好说的
  61. void dfs(int f, int u, int d) {
  62. for (int i = , sz = vec[u].size(); i < sz; i++) {
  63. // 因为线段树记录的是深度 所以就可以把当前结点以及深度差为k的全部更新一遍
  64. update(, , n, d, min(n, d + vec[u][i].first), vec[u][i].second);
  65. }
  66. //接下来dfs遍历的时候的update操作不会影响到父节点了 所以可以直接query得到答案
  67. res[u] = query(, , n, d);
  68. for (int i = head[u]; ~i; i = edge[i].next) {
  69. int v = edge[i].to;
  70. if (v == f) continue;
  71. // 深度位置是共享的 比如 1既连接2又连接3 上面更新了深度为1,2的 在线段树上 2代表的就是2和3的权值
  72. dfs(u, v, d + );
  73. }
  74. for (int i = ; i < vec[u].size(); i++) {
  75. //回溯取消标记
  76. update(, , n, d, min(n, d + vec[u][i].first), -vec[u][i].second);
  77. }
  78. }
  79. int main() {
  80. scanf("%d", &n);
  81. tot = ;
  82. memset(head, -, sizeof(head));
  83. for (int i = , u, v; i < n - ; i++) {
  84. scanf("%d%d", &u, &v);
  85. addedge(u, v);
  86. addedge(v, u);
  87. }
  88. scanf("%d", &m);
  89. while (m--) {
  90. int v, d, x;
  91. scanf("%d%d%d", &v, &d, &x);
  92. vec[v].push_back(make_pair(d, x));
  93. }
  94. dfs(-, , );
  95. for (int i = ; i <= n; i++) {
  96. printf("%I64d", res[i]);
  97. if (i == n) puts("");
  98. else putchar(' ');
  99. }
  100. return ;
  101. }

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. Linux 内核协议栈 学习资料

    终极资料 1.<Understanding Linux Network Internals> 2.<TCP/IP Architecture, Design and Implement ...

  2. CentOS下安装PHP

    今天終於進行了第三次的在linux下的php安裝,在安裝之前我進行了網站訪問測試. 第一步,先查看mysql.apache這兩項系統服務是否已經自動啟動了,chkconfig –list mysql. ...

  3. Python从菜鸟到高手(8):print函数、赋值与代码块

    1.神奇的print函数   print函数相信读者一定对它不陌生,因为在前面的章节,几乎每个例子都使用了print函数,这个函数的功能就是在控制台输出文本.不过print在输出文本时还可以进行一些设 ...

  4. 来,看看MySQL 5.6, 5.7, 8.0的新特性

    对于MySQL的历史,相信很多人早已耳熟能详,这里就不要赘述.下面仅从产品特性的角度梳理其发展过程中的里程碑事件. 1995年,MySQL 1.0发布,仅供内部使用. 1996年,MySQL 3.11 ...

  5. POST BOY : Restful API 调试工具

    在使用asp.net webapi开发中,一般情况下会使用一些工具来模拟请求. 其中有一款chrome浏览器插件POST MAN比较不错. 但是由于国内google服务使用不稳定,所以我自己写了一个简 ...

  6. matplot绘图基本使用

    先看一个最简单的例子 import matplotlib.pyplot as plt plt.figure() plt.subplot(211) plt.plot([1,2,3], color=''r ...

  7. c++继承实例

    #include <iostream> #include <vector> #include <string> using namespace std; class ...

  8. 使用jmeter来发送json/gzip格式数据 --------笔记

    一.使用jmeter来发送gzip数据 有时候我们需要模拟在客户端将数据压缩后, 发送(post)到服务器端. 通常这种情况,会发生在移动终端上. 这样做的好处, 是可以节省流量.  当然, 服务器返 ...

  9. <c:forEach varStatus="status">中 varStatus的作用

    varStatus是<c:forEach>jstl循环标签的一个属性,varStatus属性. varStatus=“status”事实上定义了一个status名的对象作为varStatu ...

  10. 配置router列表

    import Vue from "vue"; import VueRouter from 'vue-router'; import Star from '../components ...