2023暑假信友队集训结营总结
线段树的拓展应用——动态开点权值线段树
知识点讲解
动态开点线段树
故名思义,将要增加新的点,就对应的开此点,从而保证下标为值域,维护所存的值。
与普通线段树不同的是pushdown
如果左右儿子没有,在此操作下需要新建,可以利用计数变量tot进行计算
需要注意的是线段树的大小, 设值域的大小为
需要注意的是mid = (l + r - 1) / 2,这样可以处理l,r均为负数
权值线段树
类似于对于线段树的每一叶子节点当成一个桶,如
例题引入
普通平衡树
可以通过动态开点的权值线段树进行计算
对于操作insert,相当于在权值线段树的位置x的值加1
对于操作del,相当于在权值线段树的位置x的值减1
对于操作rnk,相当于求有多少个数比x小,对应的区间查询也就是
对于操作kth,可以借平衡树的思想,当前左子树的权值如果小于k,递归到右子树,并且k要减去左子树的权值。否子这届递归至左子树即可
对于操作pre相当于查找kth(rnk(x) - 1),即找到排名比x小的那一个数对应的值。
对于操作nxt相当于查找kth(rnk(x + 1)),因为排名定义为比当前数小的数的个数 +1,所以此处为x+1即可。
可持久化线段树 2
可以通过动态开点的权值线段树并且进行历史版本的维护从而进行计算
发现每一次操作至多有
如图:
那么对于初始序列可以看成将每一个数都逐步插入线段树
求
这是建树的过程
void build(int l, int r) {
tot = 1;
lfor(i, l, r) root[i] = ++ tot, insert(root[i - 1], root[i], a[i], 1);
}
结营总结
在这一个月中,我学到了许多新的算法,比如说操作树,线段树二次递归,四边形不等式等等。同时也结识到了很多大佬。我对于写题的心态也逐渐从模板化变成可以理解算法的主要思想,利用此构建程序的坚持爆0,但是每次比赛都新算法都丰富了我的视野,让我学习到了更多知识。最后,再祝大家在这一年例