树上差分

树上差分分析

使点x到点y的路径上(链上),全加上一个值,可以选择使用树上差分(不用线段树乱搞....

首先,和普通的差分一样,要有一个tag。然而,对于一个结点,我们需要求出它全部儿子的tag之后,才能算它的tag,进而算出它的值。所以,我们需要每个节点开一个tag(不然在依次遍历儿子的时候,轻儿子的tag不就乱了嘛...会影响的嘛)(前一个括号纯属口胡,就是一个博主的sb错误)

具体操作:(cf意为差分数组)

cf[x] + 1

cf[y] + 1

cf[ lca(x,y) ] - 1 //lca(x,y)算了两遍

cf[ fa[ lca(x,y) ] ] - 1 //为了不对其它的链产生影响

裸栗题

https://www.luogu.org/problem/P3258

这题注意一下: 如果出现这样的情况:x~y, y~z, 即连续进行差分, 需要注意:cf[y]加了两次,而这题中,y是不用加两次的,所以把ans[y]--,即可 (这个操作引题而异吧,自己多想想

  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. const int MAXN = 300000+99;
  5. const int MAXM = MAXN<<1;
  6. int n;
  7. struct node{
  8. int size, deep, son, tp, fa, cf, tag;
  9. }a[MAXN];
  10. int visit[MAXN];
  11. int head[MAXN], cnt;
  12. struct seg{
  13. int y, next;
  14. }e[MAXM];
  15. void add_edge(int x, int y) {
  16. e[++cnt].y = y;
  17. e[cnt].next = head[x];
  18. head[x] = cnt;
  19. }
  20. void dfs1(int x, int fa) {
  21. a[x].deep = a[fa].deep + 1;
  22. a[x].fa = fa;
  23. a[x].size = 1;
  24. for(int i = head[x]; i; i = e[i].next)
  25. if(e[i].y != fa) {
  26. dfs1(e[i].y , x);
  27. a[x].size += a[e[i].y].size ;
  28. a[x].son = a[a[x].son].size > a[e[i].y].size ? a[x].son : e[i].y;
  29. }
  30. }
  31. void dfs2(int x, int tp) {
  32. a[x].tp = tp;
  33. if(a[x].son) dfs2(a[x].son , tp);
  34. for(int i = head[x]; i; i = e[i].next)
  35. if(e[i].y != a[x].fa && e[i].y != a[x].son) {
  36. dfs2(e[i].y, e[i].y);
  37. }
  38. }
  39. int lca(int x, int y) {
  40. while(a[x].tp != a[y].tp) {
  41. if(a[a[x].tp].deep < a[a[y].tp].deep) swap(x, y);
  42. x = a[a[x].tp].fa;
  43. }
  44. return a[x].deep < a[y].deep ? x : y;
  45. }
  46. void dfs3(int x) {
  47. if(a[x].son == 0) {
  48. a[x].tag += a[x].cf;
  49. // printf("tag_%d : %d\n",x, a[x].tag);
  50. return ;
  51. }
  52. for(int i = head[x]; i; i = e[i].next)
  53. if(e[i].y != a[x].fa) {
  54. dfs3(e[i].y);
  55. a[x].tag += a[e[i].y].tag ;
  56. }
  57. a[x].tag += a[x].cf ;//实际上还要在后面写上a[x].ans = ....
  58. //但这题木有初值,所以我就直接用tag了
  59. // printf("tag_%d : %d\n",x, a[x].tag);
  60. }
  61. int main() {
  62. scanf("%d",&n);
  63. for(int i = 1; i <= n; i++) scanf("%d",&visit[i]);
  64. int x,y;
  65. for(int i = 1; i < n; i++) {
  66. scanf("%d%d",&x, &y);
  67. add_edge(x,y);
  68. add_edge(y,x);
  69. }
  70. dfs1(1, 0);
  71. dfs2(1, 1);
  72. int Lca;
  73. for(int i = 1; i < n; i++) {
  74. a[visit[i]].cf++;
  75. a[visit[i+1]].cf++;
  76. Lca = lca(visit[i], visit[i+1]);
  77. a[Lca].cf--;
  78. a[a[Lca].fa].cf--;
  79. }
  80. dfs3(1);
  81. for(int i = 2; i <= n; i++) a[visit[i]].tag--;
  82. for(int i = 1; i <= n; i++) printf("%d\n",a[i].tag);
  83. // for(int i = 1; i <= n; i++) printf("cf_%d : %d\n",i, a[i].cf);
  84. return 0;
  85. }
  86. /*
  87. 5
  88. 1 4 5 3 2
  89. 1 2
  90. 2 4
  91. 2 3
  92. 4 5
  93. */

luoguP3258 [JLOI2014]松鼠的新家的更多相关文章

  1. luoguP3258 [JLOI2014]松鼠的新家 题解(树上差分)

    P3258 [JLOI2014]松鼠的新家  题目 树上差分:树上差分总结 #include<iostream> #include<cstdlib> #include<c ...

  2. [luoguP3258] [JLOI2014]松鼠的新家(lca + 树上差分)

    传送门 需要把一条路径上除了终点外的所有数都 + 1, 比如,给路径 s - t 上的权值 + 1,可以先求 x = lca(s,t) 类似数列上差分的思路,可以给 s 和 f[t] 的权值 + 1, ...

  3. BZOJ 3631: [JLOI2014]松鼠的新家( 树链剖分 )

    裸树链剖分... ------------------------------------------------------------------- #include<bits/stdc++ ...

  4. 3631: [JLOI2014]松鼠的新家

    3631: [JLOI2014]松鼠的新家 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 707  Solved: 342[Submit][Statu ...

  5. [填坑]树上差分 例题:[JLOI2014]松鼠的新家(LCA)

    今天算是把LCA这个坑填上了一点点,又复习(其实是预习)了一下树上差分.其实普通的差分我还是会的,树上的嘛,也是懂原理的就是没怎么打过. 我们先来把树上差分能做到的看一下: 1.找所有路径公共覆盖的边 ...

  6. P3258 [JLOI2014]松鼠的新家

    P3258 [JLOI2014]松鼠的新家倍增lca+树上差分,从叶子节点向根节点求前缀和,dfs求子树和即可,最后,把每次的起点和终点都. #include<iostream> #inc ...

  7. 洛谷 P3258 [JLOI2014]松鼠的新家 解题报告

    P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

  8. 【洛谷】【lca+树上差分】P3258 [JLOI2014]松鼠的新家

    [题目描述:] 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n(2 ≤ n ≤ 300000)个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真 ...

  9. [Luogu 3258] JLOI2014 松鼠的新家

    [Luogu 3258] JLOI2014 松鼠的新家 LCA + 树上差分. 我呢,因为是树剖求的 LCA,预处理了 DFN(DFS 序),于是简化成了序列差分. qwq不讲了不讲了,贴代码. #i ...

随机推荐

  1. 转载:关于STM32硬件I2C读写EEPROM代码实现原理的理解与总结

    http://home.eeworld.com.cn/my/space-uid-716241-blogid-655190.html 一.I2C协议简介 I2C是两线式串行总线,用于连接微控制器及其外围 ...

  2. 「MacOS」将网站转换为应用程序,只需一个Unite

    unite mac有着非常强大的功能,能够轻松的将网站转换为macOS上的应用程序,除了现代化的网页浏览功能以外,Unite for Mac下载还包括特定于macOS的功能,通知,TouchBar支持 ...

  3. 【PAT甲级】Public Bike Management 题解

    题目描述 There is a public bike service in Hangzhou City which provides great convenience to the tourist ...

  4. CF1269A Equation

    题目链接 题意 要找两个合数,使他们两个的差为\(n\),\(n\)为题目给出的数 思路 我们可以枚举减数\(now\),判断一下是不是质数,如果是质数就让\(now++\),然后用一个数\(tot\ ...

  5. python做中学(九)定时器函数的用法

    程序中,经常用到这种,就是需要固定时间执行的,或者需要每隔一段时间执行的.这里经常用的就是Timer定时器.Thread 类有一个 Timer子类,该子类可用于控制指定函数在特定时间内执行一次. 可以 ...

  6. 使用php开发,基于swoole扩展开发的工具 swoole-crontab 作业/任务调度

    Swoole-Crontab(基于Swoole扩展) 1.概述 基于swoole的定时器程序,支持秒级处理. 异步多进程处理. 完全兼容crontab语法,且支持秒的配置,可使用数组规定好精确操作时间 ...

  7. 【计算机网络】如何让Ajax通信过程携带Cookie呢?

    Ajax 1. 介绍一下ajax并代码实现 1.1 基本概念 JavaScript 和XML(Asynchronous JavaScript And XML).简单点说,就是使用 XMLHttpReq ...

  8. java war包 路径--解决war包中文件路径问题

    https://blog.csdn.net/u013409283/article/details/51480948 转自:http://free-chenwei.iteye.com/blog/1507 ...

  9. 在.net 程序中使用Mustache模板字符串

    今天弄了一个配置随着使用环境动态切换的功能,一个基本的思路是: 将配置配置为模板的形式, 根据不同的环境定义环境变量 根据环境变量渲染模板,生成具体的配置 这里面就涉及到了一个字符串模板的功能,关于模 ...

  10. WPF中DataGrid在没有数据的时候也可以显示水平滚动条

    今天做项目中遇到个问题,就是页面加载后默认DataGrid是不加载数据的,但是DataGrid的列很多,就导致了运行效果上,此窗口的DataGrid没有水平滚动条,类似图片的效果. 经过百度和摸索,使 ...