bzoj 1146树链剖分

我用的是此题的树链剖分方法,此题时限50S。。。。

首先将树按链重新标号,然后将一段链给放到线段树中取。由于求u到v的k大值,那么我们可以对于一段链中二分查找对于某一个值小于这个值的个数有多少个,那么我们就可以知道这个值如果恰好是第k大的就是答案所求。用线段树的话可以将一段区间的值快速求出来

实现就是对于线段树表示表示区间的节点,对于那一段区间我们建立一个二叉搜索树(我用的treap,用于统计大于某个值的个数有多少个),然后对于每一个二分答案,我们对于这个值在u到v的树链上求小于这个值的答案有多少个就好了,直接按树链剖分的方法往一端靠上去求累计和就好了。

其总的复杂度是n(logn)^4其实想想这个复杂度对于一组数据已经接近n^2了但是考虑到线段树的区间更新,我们其实区间的查询能大大提高效率,20s可以过

这题思路这样差不多就很好写了,就是编码复杂点了。。。

这里建树忧伤死我了。。。。下面是我写treap的过程。。。

1、treap答案最多的有80000个节点,最开始的方法是treap建立静态的数组,但是考虑线段树是8000*4在加上每个treap起码有8000*(2+3)大小, 开不下。。。。。忧伤啊

2、然后我又写了个c++动态生成数组的treap,每次生成线段树r-l+4的数组大小,但是任然是静态的内存池,过到了第7组就re了,因为我发现每次删除一个节点后在生成节点内存池下标往后走。。。忧伤

你可能感兴趣的:(bzoj 1146树链剖分)