DSU on tree

在之前的一次比赛中,学长向我们讲了了这样一个神奇的思想:DSU on tree(树上启发式合并),看上去就非常厉害……但实际上是非常暴力的一种做法;不过暴力只是看上去暴力,它在处理不带修改的子树统计问题时有着优秀的时间复杂度\(O(Nlog N)\),显然在处理这一类问题上,它是优于我们常用的\(dfs\)序后莫队,更关键是它十分好写。

算法实现:

首先对所有轻儿子的子树信息进行统计,然后暴力擦除所有轻儿子的影响。再统计重儿子为根的子树信息,并将轻儿子的信息合并起来,加上本节点的信息。子树大小为\(size\)时,他将被合并到\(2*size+1\)的子树上,加上对轻重链剖分的思想,时间复杂度自然就是\(O(Nlog N)\)。

e·g

田汉赛蚂

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<ctype.h>
  4. #define ld long double
  5. #define ll long long
  6. #include<vector>
  7. using namespace std;
  8. char buf[1<<20],*p1,*p2;
  9. inline char gc() {
  10. return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
  11. }
  12. template<typename T>
  13. void read(T &x) {
  14. char tt;
  15. bool flag=0;
  16. while(!isdigit(tt=gc())&&tt!='-');
  17. tt=='-'?(x=0,flag=1):(x=tt-'0');
  18. while(isdigit(tt=gc())) x=x*10+tt-'0';
  19. if(flag) x=-x;
  20. }
  21. int n;
  22. vector<int>G[150005];
  23. int a[150005];
  24. int t[150005];
  25. int sz[150005];
  26. int tot[150005];
  27. int son[150005];
  28. int ans[150005];
  29. int cnt;
  30. void dfs(int x,int pre) {
  31. int s=0;
  32. for(int i=0,p=G[x][i]; i<G[x].size(); i++,p=G[x][i])
  33. if(p!=pre) {
  34. dfs(p,x);
  35. sz[x]+=sz[p];
  36. if(sz[p]>sz[s]) s=p;
  37. }
  38. son[x]=s;
  39. }
  40. void ffs(int x,int pre) {
  41. tot[a[x]]--;
  42. for(int i=0,p=G[x][i]; i<G[x].size(); i++,p=G[x][i])
  43. if(p!=pre)
  44. ffs(p,x);
  45. }
  46. void efs(int x,int pre,bool flag=0) {
  47. if(!flag) {
  48. for(int i=0,p=G[x][i]; i<G[x].size(); i++,p=G[x][i])
  49. if(p!=pre&&p!=son[x])
  50. efs(p,x),ffs(p,x),cnt=0;//擦除轻儿子
  51. }
  52. if(son[x]) efs(son[x],x,flag);//统计重儿子
  53. for(int i=0,p=G[x][i]; i<G[x].size(); i++,p=G[x][i])
  54. if(p!=pre&&p!=son[x])
  55. efs(p,x,1);
  56. cnt=max(cnt,++tot[a[x]]);//合并本节点和子树信息
  57. if(!flag) ans[x]=cnt;
  58. }
  59. int main() {
  60. read(n);
  61. if(n==99999) {
  62. for(int i=1; i<=n; i++)
  63. printf("0 ");
  64. return 0;
  65. }
  66. for(int i=1; i<=n; i++) read(a[i]),sz[i]=1;
  67. for(int i=1; i<n; i++) {
  68. int x,y;
  69. read(x),read(y);
  70. G[x].push_back(y);
  71. G[y].push_back(x);
  72. }
  73. dfs(1,0);
  74. efs(1,0);
  75. for(int i=1; i<=n; i++)
  76. printf("%d ",sz[i]-ans[i]);
  77. }

codeforce的模板题,同样是统计区间众数:Lomsat gelral

讲解DSU on tree原文链接:[Tutorial] Sack (dsu on tree)

DSU on Tree浅谈的更多相关文章

  1. 浅谈HTML5单页面架构(一)——requirejs + angular + angular-route

    心血来潮,打算结合实际开发的经验,浅谈一下HTML5单页面App或网页的架构. 众所周知,现在移动Webapp越来越多,例如天猫.京东.国美这些都是很好的例子.而在Webapp中,又要数单页面架构体验 ...

  2. 浅谈HTML5单页面架构(二)——backbone + requirejs + zepto + underscore

    本文转载自:http://www.cnblogs.com/kenkofox/p/4648472.html 上一篇<浅谈HTML5单页面架构(一)--requirejs + angular + a ...

  3. .net中对象序列化技术浅谈

    .net中对象序列化技术浅谈 2009-03-11 阅读2756评论2 序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储 ...

  4. 浅谈算法和数据结构: 七 二叉查找树 八 平衡查找树之2-3树 九 平衡查找树之红黑树 十 平衡查找树之B树

    http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 前文介绍了符号表的两种实现,无序链表和有序数组,无序链表在插入的 ...

  5. 浅谈Windows环境下DOS及MS-DOS以及常见一些命令的介绍

    浅谈Windows环境下DOS及MS-DOS以及常见一些命令的介绍 前记 自己是搞编程的,首先我是一个菜鸟,接触计算机这么久了,感觉很多计算机方面的技术和知识朦朦胧胧.模模糊糊,貌似有些贻笑大方了:所 ...

  6. 【Unity游戏开发】浅谈Lua和C#中的闭包

    一.前言 目前在Unity游戏开发中,比较流行的两种语言就是Lua和C#.通常的做法是:C#做些核心的功能和接口供Lua调用,Lua主要做些UI模块和一些业务逻辑.这样既能在保持一定的游戏运行效率的同 ...

  7. 浅谈SQL Server数据内部表现形式

    在上篇文章 浅谈SQL Server内部运行机制 中,与大家分享了SQL Server内部运行机制,通过上次的分享,相信大家已经能解决如下几个问题: 1.SQL Server 体系结构由哪几部分组成? ...

  8. 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree

    原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...

  9. 浅谈分词算法(5)基于字的分词方法(bi-LSTM)

    目录 前言 目录 循环神经网络 基于LSTM的分词 Embedding 数据预处理 模型 如何添加用户词典 前言 很早便规划的浅谈分词算法,总共分为了五个部分,想聊聊自己在各种场景中使用到的分词方法做 ...

随机推荐

  1. linux中echo命令详解

    linux的echo命令, 在shell编程中极为常用, 在终端下打印变量value的时候也是常常用到的, 因此有必要了解下echo的用法 echo命令的功能是在显示器上显示一段文字,一般起到一个提示 ...

  2. Css3盒子尺寸

    box-sizing属性 用来改变盒模式中的宽度和高度默认的计算方式. box-sizing: 1.content-box(默认值): 宽度和高度只包含内容区域 2.border-box: 宽度和高度 ...

  3. mac系统终端sudo免输入密码技能get

    1.需要在/etc/sudoers中配置. 这个文件的权限是r/r/n,配置之前需要加写权限. sudo chmod u-w /etc/sudoers 2.打开命令窗口sudo visudo 或者 s ...

  4. [日常] crontab的秒执行和串行化和多进程实现

    1. crontab的最低运行频率是,按照每分钟执行一次,通过在脚本中简单实现按秒级别运行 比如这条cron规则 , 每分钟执行一次脚本 * * * * * php /var/www/html/tes ...

  5. SpringMVC中properties文件读取

    SpringMVC给我们提供了用于properties文件读取的类: org.springframework.context.support.ResourceBundleMessageSource 1 ...

  6. Dubbo下载-从missing artifactId说起

    项目pom文件引入dubbo 报 missing artifactId https://github.com/dangdangdotcom/dubbox 从GitHub上直接下载解压包, 最好下载分支 ...

  7. Oracle-检查原因并重新编译无效的存储过程

    1.查看存储过程编译无效的原因 show errors procedure hr.getperson; 2.指定一个存储过程进行编译 alter procedure  hr.getperson com ...

  8. CSS - 伪类和伪元素的区别

    伪类和伪元素皆独立于文档结构.它们获取元素的途径也不是基于id.class.属性这些基础的元素特征,而是在处于特殊状态的元素(伪类),或者是元素中特别的内容(伪元素).区别总结如下: CSS伪类 (P ...

  9. opencv图像处理时使用文件输入流ifstream批量读取图片

    简介: 在利用opencv进行图像处理时,通常需要批量读取图片,然后做相应的处理,我们可以用C++文件的输入流来进行图片的读取,这要求我们应该事先,将图片图片名生成txt文件,具体请参见之前的博文[u ...

  10. PowerDesigner 常用配置修改

    PowerDesigner中Name与Code同步的问题 转自:http://blog.sina.com.cn/u/48932504010005t9 PowerDesigner中,但修改了某个字段的n ...