树套树乱讲
树状数组套线段树
先学会主席树。
主席树可以被理解为一个二维平面,其中n棵树可以视作横轴,每棵树中的坐标范围(也就是线段树的坐标范围)可以视作纵轴。这样一来就是用主席树维护了一些在二维平面上的点,给定\(a,b,c,d\),可以在\(O(\log{n})\)的时间内求出满足\(a\le x_i\le b,c\le y_i\le d\)的\(i\)的数量。
而树状数组套线段树就是把这个问题动态化。
对于上述的问题,我们是通过对主席树直接维护前缀和,查询时两棵主席树相减,再在区间\([c,d]\)上查询答案的。既然已经维护了前缀和,那么一个单点修改就会涉及到\(n\)棵主席树从而使修改的时间复杂度炸裂。
那么现在我们就考虑用更为灵活的树状数组来维护前缀和。
把主席树的前缀和用树状数组的形式表示,每次单点修改时在\(\log{n}\)棵线段树上修改,查询时也是在\(\log{n}\)棵线段树上查。
时间复杂度\(O(n\log^2{n})\)
动态区间Kth
支持数组的单点修改,区间查Kth
单点修改就是树状数组的单点修改。
用树状数组维护前缀和,这时一个区间可以用\(\log{n}\)棵线段树与\(\log{n}\)棵线段树作差的形式来表示。
在线段树上二分,复杂度\(O(n\log^2{n})\) 代码1.9k
三位偏序(陌上花开)
第一维排序第二维树状数组第三维权值线段树
做完了,代码1.5k
【模板】二逼平衡树
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1、查询k在区间内的排名
2、查询区间内排名为k的值
3、修改某一位值上的数值
4、查询k在区间内的前驱(前驱定义为严格小于x,且最大的数,若不存在输出-2147483647)
5、查询k在区间内的后继(后继定义为严格大于x,且最小的数,若不存在输出2147483647)
树状数组套线段树。
1、查k的排名就是查区间内\([1,k-1]\)的数的个数+1
2、排名为k的值,见动态区间Kth
3、树状数组修改
4、相当于操作二查排名为“\([1,k-1]\)内数的个数”的值
5、相当于操作二查排名为“\([1,k]\)内数的个数+1”的值
时间复杂度\(O(n\log^2{n})\),代码3.2k
[ZJOI2013]K大数查询
你有n个位置,每个位置初始是空的。
一种操作是在a位置到b位置上每个位置插入一个元素c
一种操作是查询a位置到b位置上第k大的数
报告!我会整体二分!不好意思,强制在线。
首要考虑的是内外层的关系:位置和权值哪个作为内层,哪个作为外层?
方案一:外层位置内层权值。
发现操作一是一个区间修改,操作二是一个区间查询。不知道能不能写。
方案二:外层权值内层位置。
发现操作一是一个单点修改,操作二是一个线段树上二分。
所以就线段树套线段树,即线段树上的每一个点都是一棵线段树的根。
时间复杂度\(O(n\log^2{n})\),代码1.5k
[HNOI2016]网络
给你一棵树,支持如下三种操作:
1、在树上插入一条两端点为\(u,v\),权值为\(w\)的链。
2、删除之前插入的某一条链。
3、查询未经过点\(x\)的链中的权值最大值
可在线。
首先把链剖成\(\log{n}\)个区间(dfs序上的区间)。
把区间反转,在不在这\(\log{n}\)个区间范围内的区域做覆盖。
这样就可以查询覆盖了\(x\)点的链中的最大值就可以了。
由于有删除操作所以线段树上的每个节点开一个删除堆。
时间复杂度\(O(n\log^3{n})\) 代码3.2k
后记
树状数组套平衡树我没写过,yyb说用来写三维偏序然而三位偏序不是被我树状数组套线段树水过去了吗
总之,大家根据自己的代码风格以及对这些数据结构的熟练程度进行取舍吧
还有对于那些没有强制在线的题目,采用cdq分治或者是整体二分都是不错的选择。
原文地址:https://www.cnblogs.com/zhoushuyu/p/8486133.html