题意:有n(<=1e5)个点的树,每个点都有颜色(颜色可能重复),有m(<=1e5)个询问,每次询问(x,d)问在x的子树中,与x的距离不超过d的节点有多少种不同的颜色。强制要求在线。

分析:

  Part A:先考虑颜色不重复的

  如果我们能把每个节点的子树信息建成以深度作为下标的线段树,那么就能很简单地应付查询了

  这个信息也很明显,就是下标表示深度,权值表示该深度的节点有多少种不同颜色(注意我们先考虑颜色没有重复的)

  那么我们可以先对每个节点自己建一个权值线段树,把自己对应深度的那个位置放个1,其它位置放0

  从底向上合并线段树,那么我们就可以得到表示每个节点子树的线段树辣!

  但是每个点暴力开线段树是肯定MLE的

  这个时候我们发现我们建的权值线段树只有一个位置是1,其它都是0,受到主席树节约空间的启发,我们最初建线段树的时候只需要建logn的空间(也就是一边)

  然后合并的时候也类似主席树的那样,有信息更新的节点就重新开个节点来表示,否则直接利用原来建过的节点

  分析一下复杂度,对于n个点,初始建logn的线段树,是O(nlogn)的

  那合并呢?考虑均摊,对于有k个值不是0的一颗线段树,均摊地认为它节点个数是Ck的,而不是Cklogn,那么一路合并上去,就是O(nlogn)的时间(虽然常数有点大)

  ok这都是可以接受的,但是很显然我们这种做法对于同种颜色会重复叠加,那么如何处理呢?

  Part B

  在处理序列里这种颜色重复问题时候,以前都是弄一个pre[x]表示该位置前面的一个同颜色的节点的位置,但这在树上就不适用了,但是可以类比,树上的顺序关系肯定就是深度的大小;而且这题需要合并,那就不能直接用数组记录,需要用线段树处理合并。

  方法是对每个点再建一个线段树,下标表示颜色(1..n),权值表示该颜色在当前子树中出现的最小深度是多少

  同样从叶子节点开始向上合并,合并的时候也是同样将两棵树一直合并到叶子节点,两边取个min就行了

  关键是这是怎样修正我们的答案的呢?

  我们对这第二棵线段树维护到叶节点的时候,这说明我们在合并我们当前的第一棵颜色的时候,当前颜色多算了,那么就把这个max的深度作为下标在第一棵线段树中减掉

  那么减掉多少呢?

  实际上就是减1,因为自底向上,一直保持这样的操作,那么每次多加的次数一定就是1,所以减掉的次数也是1

  注意更新第一棵线段树中的值的时候,也要动态开辟新的节点

  复杂度也是O(nlogn)的

  因为每次修改/合并都要开辟logn的节点,所以整个需要的空间大概是2*m*(3*logn)

  这样的空间是不会爆的,当然也可以类似主席树的那种对下标进行重回收(还记得大明湖畔的zoj2112吗)

[HDU5709]Claris Loves Painting(动态开点线段树+合并)的更多相关文章

  1. [Vani有约会]雨天的尾巴——树上差分+动态开点线段树合并

    题目描述 首先村落里的一共有n座房屋,并形成一个树状结构.然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋z类型的救济粮. 然后深绘里想知道,当所 ...

  2. codeforces 893F - Physical Education Lessons 动态开点线段树合并

    https://codeforces.com/contest/893/problem/F 题意: 给一个有根树, 多次查询,每次查询对于$x$i点的子树中,距离$x$小于等于$k$的所有点中权值最小的 ...

  3. [2016湖南长沙培训Day4][前鬼后鬼的守护 chen] (动态开点线段树+中位数 or 动规 or 贪心+堆优化)

    题目大意 给定一个长度为n的正整数序列,令修改一个数的代价为修改前后两个数的绝对值之差,求用最小代价将序列转换为不减序列. 其中,n满足小于500000,序列中的正整数小于10^9 题解(引自mzx神 ...

  4. [bzoj 3531][SDOI2014]旅行(树链剖分+动态开点线段树)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3531 分析: 对于每个颜色(颜色<=10^5)都建立一颗线段树 什么!那么不是M ...

  5. 【BZOJ-4636】蒟蒻的数列 动态开点线段树 ||(离散化) + 标记永久化

    4636: 蒟蒻的数列 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 247  Solved: 113[Submit][Status][Discuss ...

  6. codeforces 915E - Physical Education Lessons 动态开点线段树

    题意: 最大$10^9$的区间, $3*10^5$次区间修改,每次操作后求整个区间的和 题解: 裸的动态开点线段树,计算清楚数据范围是关键... 经过尝试 $2*10^7$会$MLE$ $10^7$会 ...

  7. CF915E Physical Education Lessons 动态开点线段树

    题目链接 CF915E Physical Education Lessons 题解 动态开点线段树 代码 /* 动态开点线段树 */ #include<cstdio> #include&l ...

  8. 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)

    题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...

  9. NOIP2017 列队——动态开点线段树

    Description: Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n×m名学生,方阵的行数为  ...

随机推荐

  1. sql语句中截取字符串

    今天在开发过程中因为要用到合并单元格,在程序里实现了以后,查出来的数据太长,都把格式撑大了,后来想想可以在sql语句查询的时候就截取,就去网上找了一下,挺好用,就转了过来: 合并单元格: /// &l ...

  2. elasticsearch.yml 配置说明

    cluster.name: 指定node所属的cluster. node.name: 本机的hostname. node.master: 是否可以被选举为master节点.(true or false ...

  3. 洛谷 P1886 滑动窗口 (数据与其他网站不同。。)

    题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...

  4. windows ubuntu bcdeditor

    双系统. 先装windows,后装ubuntu12.04 为了避免grub引导,所以安装bcdeditor. 平时使用没有什么不适,可是每次linux升级内核以后,grub列表可能就会消失,自然是不能 ...

  5. 在死循环中使用Scanner获得键盘输入

    1. 编译时无错误和警告,且运行过程中无异常的代码示例 //编译时无错误和警告,且运行过程中无异常的代码示例package scanner_test; import java.util.*; publ ...

  6. new Buffer 生成二进制数据

    node编辑环境下: > new Buffer("admin")<Buffer 61 64 6d 69 6e> 通过post请求,服务端接收到是流数据,必须把流数 ...

  7. 懒癌晚期学图论的时候自己用C语言写了个求可达性矩阵的算法~

    可达性矩阵算法~ 直接上代码 #include <iostream> #include <cstring> using namespace std; #define n 5 v ...

  8. LUA-点号和冒号

    由于LUA中是模拟类,没有class, 所以这里是使用.号来访问实例的成员 re.SetActive(re, re.activeSelf == false); 而冒号:  则是种语法糖,省略了上面代码 ...

  9. find -print0和xargs -0原理及用法

    平常我们经常把find和xargs搭配使用,例如: find . -name "*.txt" | xargs rm 但是这个命令如果遇到文件名里有空格或者换行符,就会出错.因为xa ...

  10. win7右键菜单不见解决办法

    直接 开始 运行: cmd /k reg add "HKEY_CLASSES_ROOT\Directory\Background\shellex\ContextMenuHandlers\Ne ...