关于树套树。。。

上一道题正解是cdq分治,想用动态开点的二维线段树(线段树套线段树+动态开点)水过去但是没成功,但我还是不死心。。。于是我去看了道树套树的题目。。。

题目是bzoj1901(zoj2112),题意是这样的,给一个数列,单点修改和查询区间第k大。。。

如果不带修改的话,显然直接主席树就可以了。。。但是带修改的话树套树就派上用场了。。。用线段树套平衡树,或者线段树/树状数组套主席树。。。

首先是线段树套平衡树的做法。。

外层套一颗线段树维护数列,然后线段树的每个结点建立用一颗平衡树来维护该结点区间内的值,空间看起来很大,其实仔细想想,平衡树空间是o(n)的,线段树是n*2,但是线段树本身是第i层是(1<<(i-1))个,总共logn层,套上平衡树的话每层就是n个,所以总的空间复杂度是o(n*logn),然后修改只要在要修改的结点上修改结点平衡树就可以了,由于是求第k大,所以就不用pushup了,直接把路径上的结点平衡树全部修改就可以了。。。查询就直接在要查询的区间结点平衡树查询就可以了。。。等等。。。查询的时候真的能在区间结点查询吗。。。显然不能。。那怎么办。。。于是我又去看了下代码。。。。原来是这样的。。。二分第k大的数x,然后判断x是否满足区间中在该区间中属于第k大,判断方法是查询的区间[L,R]像线段树一样查询下去,知道覆盖某个结点区间位置,然后统计该结点区间比k小的数的个数,最后递归上来的时候把个数加上来,这样就知道x在[L,R]中的rank了。

至于树状数组套主席树的。。。我还没想清楚。。。有时间再搞。。。。其实用线段树套平衡树也可以求静态区间第k大的。。。不过还是主席树方便。。。。

 

你可能感兴趣的:(关于树套树。。。)