树套树乱讲

树套树乱讲

树状数组套线段树

先学会主席树。

主席树可以被理解为一个二维平面,其中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

时间: 2024-10-12 10:28:22

树套树乱讲的相关文章

树套树乱讲的代码

树套树乱讲的代码 由于部分代码的完成时间较早所以码风可能有些差异,敬请谅解. 动态区间Kth 题面 整体二分题解 #include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> using namespace std; const int N=10005; struct segment_tree{int v;int ls,rs;}t

[BZOJ3110] [Zjoi2013] K大数查询 (树套树)

Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M 接下来M行,每行形如1 a b c或2 a b c Output 输出每个询问的结果 Sample Input 2 5 1 1 2 1 1 1 2 2 2 1 1 2 2 1 1 1 2 1 2 3 Sample Output 1 2 1 HINT [

BZOJ3295 动态逆序对 树套树, 树状数组套线段树(主席树)

Orz黄学长,蒟蒻在黄学长的带领下,通过阅读黄学长的代码!终于会了这道题! 首先我想先说一下这道题的思路(准确来说是黄学长的). 很明显,树状数组应该不用讲吧!关键是内存怎么开,维护一些什么样的数据? 其实我们通过观察,很快可以发现,你维护被删的数比维护所有的数轻松多了(不管是空间上,还是时间上).所以我们就可以从这方面想!(其实我一开始的思路,因为这道题我已经看过很久了,一直想写,毕竟是白书里面的一道例题嘛!一开始,蒟蒻的我是打算这样的用树状数组套权值线段树,并且是维护所有的数,我发现空间不够

HDU 6096 树套树

思路: 网上的题解有AC自动机的,有trie树的,还有(乱搞?)的 首先把输入的那n个串按照字典序排序, 把n个串翻转以后再按照字典序排序 这样我们发现, 查的前缀在字典序排序后是一段区间, 查的后缀翻转一下在翻转后的字典序排序以后也是一段区间 这样如果不考虑重叠的问题,就是一个简单的二维数点问题,一维排序,一维线段树即可解决 如果有重叠的问题,我们需要搞出来每个字符串的长度,使给出的前缀长+后缀长>=原字符串长度 此时题目变成了三维偏序,排序后树套树即可. //By SiriusRen #in

BZOJ_3196_二逼平衡树(树套树:线段树+Treap)

描述 可以处理区间问题的平衡树. 分析 树套树.可以用线段树套Treap.人生第一道树套树的题... op1:如果在整区间,直接在该区间的treap上求解.否则分两个区间求解,然后相加.最后+1. op2:这个不太好直接做,可以二分,每次假定一个值,用这个值去做op1,以此求得一个rank=k+1的数,求rank=k的数等价与求这个数的前驱pre. op3:先删后加. op4&op5:如果在整区间,直接在该区间的treap上求解,否则分量个区间求解,pre取最大值,suc取最小值.注意有些数在有

BZOJ 3110: [Zjoi2013]K大数查询 [树套树]

3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6050  Solved: 2007[Submit][Status][Discuss] Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M接下来M行,每行形如1 a

bzoj 3295: [Cqoi2011]动态逆序对(树套树 or CDQ分治)

Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数.以下n行每行包含一个1到n之间的正整数,即初始排列.以下m行每行一个正整数,依次为每次删除的元素. Output 输出包含m行,依次为删除每个元素之前,逆序对的个数. Sample Input 5 4 1 5 3

HDU HDOJ5412(树套树

题目:要求支持带修改维护区间第k大的值.所谓的动态区间第k大. 思路:题解说的是树状数组套treap,然而没想通树状数组怎么维护...线段树的话就是把所有的值离散化一下,离线建个关于值的线段树,每个节点是一个treap,treap里的值用位置做关键字,然后做区间查询,复杂度是O(nlogn*logn).基本也是经典的树套树做法....然后赛后写了两遍都没过.....今天心血来潮再挑战一下,结果从8点调到晚上1点.其间各种爆内存各种re各种t.....随机数据对拍了好久没拍出问题来....然后一直

bzoj 1901: Zju2112 Dynamic Rankings(树套树)

1901: Zju2112 Dynamic Rankings 经典的带修改求区间第k小值问题 树套树模板,我是用的线段树套splay实现的,而且用的数组模拟的,所以可能空间略大,bzoj过了,zoj过不了. 思路很简单,用线段树维护区间,用splay维护区间内的权值,然后询问的时候,二分答案key,然后在区间内找小于key的数有多少个. 贴上模板: #include<stdio.h> #include<string.h> #include<algorithm> #def