codeforces 1076E Vasya and a Tree 树上差分

谁借莪1个温暖的怀抱¢ 2022-01-22 12:41 296阅读 0赞

题意:给你一棵1为根节点的树,初始每个节点权值为0,有m次操作,每次操作 v d x,表示将以v为根的子树,深度不超过d的所有节点加上x。

思路:dfs的性质+差分思想,dfs记录以该节点为起点的所有操作影响的深度范围,在从该节点回溯时再把影响减去,因为dfs时只会在子树中遍历,所以用这种方法就把影响限制在了子树的规定深度中。

参考博客:https://www.cnblogs.com/pkgunboat/p/9955562.html

代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. const int N=1e6+10;
  5. int n,m,vs[N],d[N],w[N];
  6. ll ans[N];
  7. vector<int> e[N];
  8. struct nd{
  9. int d,x;
  10. };
  11. vector<nd> g[N];
  12. void dfs(int u,ll val) {
  13. val+=w[d[u]];
  14. for(int i=0;i<g[u].size();i++) {
  15. int dep=min(n,d[u]+g[u][i].d);
  16. ///差分
  17. w[dep+1]-=g[u][i].x;
  18. val+=g[u][i].x;
  19. }
  20. ans[u]=val;
  21. for(int i=0;i<e[u].size();i++) {
  22. int v=e[u][i];
  23. if(!d[v]) {
  24. d[v]=d[u]+1;
  25. dfs(v,val);
  26. }
  27. }
  28. ///回溯把影响减去
  29. for(int i=0;i<g[u].size();i++) {
  30. int dep=min(n,d[u]+g[u][i].d);
  31. w[dep+1]+=g[u][i].x;
  32. }
  33. }
  34. int main() {
  35. scanf("%d",&n);
  36. for(int i=1;i<n;i++) {
  37. int x,y;
  38. scanf("%d%d",&x,&y);
  39. e[x].push_back(y);
  40. e[y].push_back(x);
  41. }
  42. scanf("%d",&m);
  43. while(m--) {
  44. int v,d,x;
  45. scanf("%d%d%d",&v,&d,&x);
  46. g[v].push_back({d,x});
  47. }
  48. d[1]=1;
  49. dfs(1,0);
  50. for(int i=1;i<=n;i++) printf("%lld ",ans[i]);
  51. return 0;
  52. }

发表评论

表情:
评论列表 (有 0 条评论,296人围观)

还没有评论,来说两句吧...

相关阅读