标题效果:

有一棵树,有两种操作模式对本树:1:表示为(1 x val),在NOx加在节点上val,然后x每个节点加上儿子- val。给每个儿子一个儿子在一起-(- val),加到没有儿子为止。2:表示为(2 x)查询x节点上的值。

做法:

因为每次改动操作改动的并非一个值,而是非常多值。那我们将该题抽象成区间改动,点查询的问题。那怎么抽象呢?能够明确的是,每次操作尽管有加有减,可是每次做加法操作。或者减法操作的都是同一部分数(也就是说,在某次加上同一个数的节点们。下次操作一定是加上或者减去同样的数),可是假设以树原来的编号为基础的话,那我们须要改动同样的数的那些节点肯定是不连续的,那就无法使用线段树或者树状数组的区间改动了。应该怎么办呢?我们考虑一下能不能将这树上的节点又一次排序,使得每次改动的值在一个连续的区间。

比方说有例如以下一棵树:


树的右边第一列代表深度,第二列代表着有着同样值(0或者1)的这些层的节点改动时都是同加或者同减的。比方第二层的节点和第四层的每一个节点在改动时进行的操作一定是全是加。或者全是减,不可能一部分节点加,一部分节点减的。



那我们怎么将每次操作须要改动的值都又一次编号为一个连续的区间呢? 如上图我们应该是又一次编号为这种:

(第一行为新数组下标。第二行为新数组存的节点序号)

这样一来,我们就把每次须要改动的值变成了连续的了,比方说改动操作为(1 1 val),那么我们须要加val的节点在新数组中的区间为[1,5],须要减val的节点在[6,10];假设改动操作为(1 2 val)那么我们须要加val的节点在新数组中的区间为[6,8],须要减val的节点在[2,3]。
那详细怎么才干编号成这样呢?我们首先将每一个节点相应的上图右边第二列的值存在d[]数组中,先从根节点(1)開始。跳层DFS。以dfs的顺序将遍历到的儿子节点一个个的加到新数组中。

遍历完之后,再对根节点的每一个儿子做一遍同样的操作就可以。(详细能够看代码)


得到这个数组之后呢,我们还要预处理出对某个点进行改动操作,我们须要在那个区间加值。在哪个区间减值。也是用dfs,每一个节点的属性能够由儿子来确定。详细看代码和凝视:
代码:
  1. #include <iostream>
  2. #include <cstdio>
  3. #include <vector>
  4. #include <algorithm>
  5. #define N 200020
  6. using namespace std;
  7. struct ee//存储须要改动哪些区间的结构体
  8. {
  9. int x1,y1,x2,y2;
  10. }e[N];
  11. vector<int> g[N];
  12. int n,m,a[N],d[N],c[N],bef[N],index=1;
  13. void dfs1(int x,int fa,int deep)//处理d[]数组
  14. {
  15. d[x]=deep;
  16. for(int i=0;i<g[x].size();i++)
  17. if(g[x][i]!=fa) dfs1(g[x][i],x,1-deep);
  18. }
  19. void dfs2(int x,int fa,int deep)//得到新数组
  20. {
  21. if(d[x]==deep) bef[x]=index++;//aft[index++]=x;//bef[i] 当中,i是原节点的编号,bef[i]是i在新数组中的下标
  22. for(int i=0;i<g[x].size();i++)
  23. if(g[x][i]!=fa) dfs2(g[x][i],x,deep);
  24. }
  25. void dfs3(int x,int fa)//预处理每一个点的属性
  26. {
  27. for(int i=0;i<g[x].size();i++)
  28. if(g[x][i]!=fa) dfs3(g[x][i],x);
  29. int ma1=bef[x],mi2=N,ma2=0;
  30. for(int i=0;i<g[x].size();i++)
  31. {
  32. if(g[x][i]==fa) continue;
  33. int cur=g[x][i];
  34. mi2=min(mi2,e[cur].x1);
  35. ma2=max(ma2,e[cur].y1);
  36. ma1=max(ma1,e[cur].y2);
  37. }
  38. e[x].x1=bef[x],e[x].y1=ma1,e[x].x2=mi2,e[x].y2=ma2;//[x1,y1]为须要加值操作的区间,[x2,y2]为须要减值操作的区间,能够由儿子确定
  39. }
  40. int getnum(int x)//以下便是树状数组的区间改动,点查询函数咯~
  41. {
  42. int rnt=0;
  43. for(int i=x;i<=n;i+=(i&(-i)))
  44. {
  45. rnt+=c[i];
  46. }
  47. return rnt;
  48. }
  49. void add(int i,int a)
  50. {
  51. while(i>=1)
  52. {
  53. c[i]+=a;
  54. i-=(i&(-i));
  55. }
  56. }
  57. int main()
  58. {
  59. scanf("%d%d",&n,&m);
  60. for(int i=1;i<=n;i++) scanf("%d",a+i);
  61. for(int i=0;i<n-1;i++)
  62. {
  63. int a,b;
  64. scanf("%d%d",&a,&b);
  65. g[a].push_back(b),g[b].push_back(a);
  66. }
  67. dfs1(1,0,1);//计算d[]数组
  68. dfs2(1,0,1);//对根节点进行处理
  69. for(int i=0;i<g[1].size();i++)
  70. dfs2(g[1][i],1,0);//对根节点的每一个儿子进行处理
  71. dfs3(1,0);//预处理
  72.  
  73. while(m--)
  74. {
  75. int ty;
  76. scanf("%d",&ty);
  77. if(ty==1)
  78. {
  79. int x,y;
  80. scanf("%d%d",&x,&y);
  81. int l1=e[x].x1,r1=e[x].y1,l2=e[x].x2,r2=e[x].y2;
  82. add(r1,y),add(l1-1,-y);
  83. if(r2!=0) add(r2,-y),add(l2-1,y);//假设不是根节点再进行减操作
  84. }
  85. else
  86. {
  87. int x;
  88. scanf("%d",&x);
  89. cout<<getnum(bef[x])+a[x]<<endl;
  90. }
  91. }
  92. return 0;
  93. }

版权声明:本文博客原创文章,博客,未经同意,不得转载。

Codeforces 383C . Propagating tree【树阵,dfs】的更多相关文章

  1. CodeForces 383C Propagating tree

    Propagating tree Time Limit: 2000ms Memory Limit: 262144KB This problem will be judged on CodeForces ...

  2. codeforces 383C Propagating tree 线段树

    http://codeforces.com/problemset/problem/383/C 题目就是说,  给一棵树,将一个节点的值+val, 那么它的子节点都会-val, 子节点的子节点+val. ...

  3. Codeforces 383C Propagating tree, 线段树, 黑白染色思想

    按深度染色,奇深度的点存反权值. #include <bits/stdc++.h> using namespace std; vector <]; ],a[],s[],vis[],i ...

  4. CodeForces 384E Propagating tree (线段树+dfs)

    题意:题意很简单么,给定n个点,m个询问的无向树(1为根),每个点的权值,有两种操作, 第一种:1 x v,表示把 x 结点加上v,然后把 x 的的子结点加上 -v,再把 x 的子结点的子结点加上 - ...

  5. Codeforces Round #381 (Div. 2)D. Alyona and a tree(树+二分+dfs)

    D. Alyona and a tree Problem Description: Alyona has a tree with n vertices. The root of the tree is ...

  6. CodeForces 343D water tree(树链剖分)

    Mad scientist Mike has constructed a rooted tree, which consists of n vertices. Each vertex is a res ...

  7. Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组

    C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...

  8. Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+ 树状数组或线段树

    C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...

  9. Codeforces Round #225 (Div. 2) E. Propagating tree dfs序+-线段树

    题目链接:点击传送 E. Propagating tree time limit per test 2 seconds memory limit per test 256 megabytes inpu ...

随机推荐

  1. win8/win10/win2012r2 存储池 冗余分析

    StorageSpace:a. Simple,相当于RAID0,无冗余,不考虑b. Two-way Mirror,双重镜像,至少2块盘,性能单盘,可以坏一块盘c. Three-way Mirror,三 ...

  2. 同步特定源代码到 omni_rom源代码目录里面

    #!/bin/bash base_path="/Volumes/Android/omnirom_5.0" #此目录是我存放源代码的目录 xiaomi_device="de ...

  3. 在基于阿里云serverCentOS6.5下安装Subversion 1.6.5服务

    近期阿里云搞了个1元免费提供云server的活动,偶心痒痒就申请了一个. 正好能够作为团队的SVNserver了,以下就来部署SVN服务吧. 一.安装基础环境 apr-1.5.0.tar.gz apr ...

  4. Android自己主动化測试——CTS測试

    一.为什么须要兼容性測试(下面称CTS)? 1.1.让APP提供更好的用户体验.用户能够选择很多其它的适合自己设备的APP.让APP更稳定. 1.2.让开发人员设计更高质量的APP. 1.3.通过CT ...

  5. perl操作sqlserver实现BCP

    #!C:\Perl64\bin #由BCP备份和恢复SQLSERVER指定表 use 5.014; #加载用户和password型材 my $username ; my $passwd; ##得到us ...

  6. 赵雅智_BroadcastReceiver短信监听

    AndroidManifest.xml 注冊广播接收者 加入权限 <?xml version="1.0" encoding="utf-8"?> &l ...

  7. iOS_17_控制开关_TabBarController_由storyboard道路

    最后效果图: main.storyboard BeyondViewController.m中有一句关键代码,设置tabbarItem图片的样式(30*30) // // BeyondViewContr ...

  8. IE6浏览器的一些问题

    背景图像缓存 // IE6 background image caching fix. try { document.execCommand("BackgroundImageCache&qu ...

  9. .NET 并行(多核)编程系列之七 共享数据问题和解决概述

    原文:.NET 并行(多核)编程系列之七 共享数据问题和解决概述 .NET 并行(多核)编程系列之七 共享数据问题和解决概述 前言:之前的文章介绍了了并行编程的一些基础的知识,从本篇开始,将会讲述并行 ...

  10. Kienct与Arduino学习笔记(2) 深度图像与现实世界的深度图的坐标

    转载请注明出处:http://blog.csdn.net/lxk7280 首先,要接触一下KinectOrbit这个摄像机库,这篇文章中有这个库的下载网址和简单的介绍:http://blog.csdn ...