#P6018. [Ynoi2010] Fusion tree

    ID: 4935 远端评测题 2000ms 500MiB 尝试: 0 已通过: 0 难度: (无) 上传者: 标签>树形结构2010O2优化字典树Trie 树

[Ynoi2010] Fusion tree

题目背景

题目背景和题意无关,可以跳过

1.前言:

Fusion Tree,中文译作融合树,是一种亚log的数据结构,与1993年由Michael L.Fredman和Dan E.Willard提出。

用途:O(logn/logw+logw)O( \log n/ \log w+ \log w )时间复杂度支持插入,删除,前驱,后继,min,max,以及用于整数排序。

信息论断言对nn个数的排序在最坏情况下需要nlognn\log n次比较,不过对这个界我们还需要一些研究。

有人证明了任意unit cost RAM算法,其中只包含加法,减法,乘法,和0比较(但是不包含除法和位运算)最坏情况下需要Ω(nlogn)\Omega(n\log n)的时间去对nn个数排序。

如果允许使用除法和位运算,他们有一个线性时间复杂度的算法,但是这个算法对unit cost滥用。

这里我们规定我们使用的计算模型的字长是w,每个输入的数都是在[0,2w1][0,2^w-1]中的整数。

2.一些记号:

对于一个集合SS和一个整数xx,定义rank(S,x)rank(S,x)为S集合中x\le x的元素个数。 对于一些非负整数aa,定义bin(a1,...,an)=2ai+...+2anbin(a_1,...,a_n)=2^{a_i}+...+2^{a_n}

对于两个非负整数a,ba,b,定义msb(u,v)msb(u,v)uuvv最高的不相同的位。

3.概述:

Fusion Tree大概可以看做是一棵特殊的B-Tree,特性:

  1. 叉数B=O(w1/5)B=O(w^{1/5})

  2. 在一次搜索时,每个在搜索路径上的节点的正确的儿子可以被O(1)O(1)确定

从这些特性我们可以看出Fusion Tree单次操作的时间复杂度是$O( \log _w(n) + \log w) = O( \log n/\log w +\log w)$的,比O(logn)O( \log n )低。

但是由于其实现方式,Fusion Tree每次对内部节点的更新复杂度是O(B4)O( B^4 )的。 为了控制Fusion Tree均摊的更新复杂度,我们将这棵B-Tree的每对叶子节点之间的部分替换为一个大小大约为O(B4)O( B^4 )的Weight Balanced Tree,只在WBT根节点发生变化的时候更新Fusion Tree的内部节点。

具体来说,我们B-Tree维护的是一个排序后的数组的分块,其中每个块都由一棵平衡二叉搜索树维护,fusion tree上只维护一个值来表示块边界,用途是指引每次插入,删除,查询在哪个块中。

可以发现这样我们把内部节点的变化次数除掉了一个B4B^4

4.压缩key的表示:

如何O(1)O(1)确定搜索路径上的一个节点的正确的儿子:

考虑一个B-Tree的节点,其上面包含了kk个key,其中B/2kBB/2 \le k \le B,记作S=u1,u2,...ukS={u_1,u_2,...u_k}

然后我们定义出B(S)B(S)表示"有区别的位的位置",用人话来说就是我们把这kk个key的trie建出来,然后所有有超过11个儿子的节点的高度构成的集合 (当然这里我们不用把trie建出来,只是这么解释比较直观,而且更能反映出其的一些性质)。

再定义一个集合K(S)K(S),为SS只保留B(S)B(S)中那些位之后的值,记作K(S)=u1,u2,...ukK(S)={u'_1,u'_2,...u'_k},发现这个压缩操作对于原集合是保序的。

对于一个任意的wbitw-bit的数uu,我们记u(S)u'(S)表示uu只保留B(S)B(S)中那些位,即把非B(S)B(S)中的位都置为00之后的值。

下面引理表达了一个压缩key的重要性质:

引理1:

B(S)B(S)排序后为c1<c2<...<crc_1<c_2<...<c_r,定义边界c0=1,cr+1=bc_0=-1,c_{r+1}=b

定义uiu'_iK(S)K(S)中任意的一个压缩后的key。

对于一个任意的wbitw-bit的数uu,满足uuiu \neq u_i

msb(u(S),ui)=cmmsb(u'(S),u'_i)=c_m,即uuuiu_i在bit位置cm+1,...,crc_{m+1},...,c_r位置处相等,但是在cmc_m处不相等,如果u(S)=uiu'(S)=u'_i,则我们记m=0m=0

如果uuuiu_i不同的最高位pp满足p>cmp>c_m,那么我们可以通过:

  1. 唯一的一个区间[cj1,cj][c_{j-1},c_j]满足pp属于这个区间

  2. uuuiu_i的大小关系

来确定rank(S,u)rank(S,u)的值。

证明平凡,把trie画出来,显然可以画成一个平面图,然后可以发现这两个可以唯一地确定出一个平面区域,这个区域中的SS集合元素个数就是rank(S,u)rank(S,u)(感觉这种东西光写一堆自然语言也不能说明正确性,需要形式化证明一下?)。

注意到这个引理虽然是对任意uiu_i成立的,但是要求uuuiu_i不相同的最高位不是B(S)B(S)中的一个点,可以发现这个uiu_i其实必须在uu"脱离"这个trie的位置,也就是pp的父亲子树中。

引理11使得我们可以将rank(S,u)rank(S,u)的计算规模降低到rank(K(S),u(S))rank(K(S),u'(S)),通过计算rank(K(S),u(S))rank(K(S),u'(S)),我们可以确定u(S)u'(S)K(S)K(S)中的前驱后继uju'_juj+1u'_{j+1}(这两个值不一定存在,但经过平凡的讨论就可以解决。

如果ujuuj+1u_j \le u \le u_{j+1},那我们已经解决了这个问题 否则我们令i=ji=j或者i=j+1i=j+1,计算出msb(ui,u)=pmsb(u_i,u)=p,然后只要我们知道了包含pp的区间[cj,cj+1][c_j,c_{j+1}],我们就可以通过引理11来确定出rank(S,u)rank(S,u)的值。

这里如果我们ujuuj+1u_j \le u \le u_{j+1},那我们已经达成了目的,不用继续考虑了。

否则如果不满足ujuuj+1u_j \le u \le u_{j+1},也就是说我们在这个sketch的过程中丢失了信息,即说明保留K(S)K(S)这些位的信息是不够的,那么pp一定不在K(S)K(S)中,也就是说i=ji=ji=j+1i=j+1pp较小的ii满足p>cmp>c_m,故可以使用引理11

计算K(S)K(S)u(S)u'(S): 我们发现没有平凡的方法可以将一个wbitw-bit的数uuO(1)O(1)时间把B(S)B(S)那些位提取出来之后放到连续的一段中(可能可以通过硬件支持实现?),即使经过了一定预处理。

其实我们不需要做到这个,可以用具有:

  1. 将需要提取出的位提取出,并放到(可以不连续)的更短的一段中

  2. 保序性

的其他变化来实现我们需要的效果。

我们可以通过一次恰当的乘法和一次与运算来实现这个:

沿用引理11的定义,设我们需要从uu中提取这些位,令C=bin(c1,...,cr)C=bin(c_1,...,c_r)

假设我们已经算出了CC,我们先通过令v=u  AND  Cv=u\;\mathrm{AND}\;C来将uu中不需要的那些位置00

然后我们将vv乘以一个量MM,从而把vv中我们需要的那些bitbit转化到一个狭窄的范围内,然后再通过一次AND\mathrm{AND}来清除掉不需要的位置 这里给出对一个量MM的存在性证明和构造:

M=bin(m1,...,mr)M=bin(m_1,...,m_r),如果我们暂时忽略交叉和进位造成的影响,那么可以认为vvMM是把c1,...crc_1,...c_r这些位置的位重新定位到了。

c1+m1,...,cr+mrc_1+m_1,...,c_r+m_r上。

如果对任意1i,jr1 \le i,j \le r,这r2r^2ci+mjc_i+m_j都是不同的,那么就不会发生交叉和进位了。

我们现在的目标是构造一个整数集合m1,...,mr{m_1,...,m_r},使得:

  1. c1+m1<c2+m2<...<cr+mrc_1+m_1<c_2+m_2<...<c_r+m_r

  2. 对任意1i,jr1 \le i,j \le rci+mjc_i+m_j都是两两不同的。

  3. 变换后的区间[c1+m1,cr+mr][c_1+m_1,c_r+m_r]"相对较小",这里的相对较小其实只要是O(poly(r))O( poly(r) )的即可,因为这样我们可以通过调整树的叉数来满足后续的条件。

引理2:

给一个rr个整数的序列,c1<...<crc_1<...<c_r,存在一个rr个整数的序列,m1,...mrm_1,...m_r,满足:

  1. c1+m1<c2+m2<...<cr+mrc_1+m_1<c_2+m_2<...<c_r+m_r

  2. 对任意1i,jr1 \le i,j \le rci+mjc_i+m_j都是两两不同的。

  3. (cr+mr)(c1+m1)r4(c_r+m_r)-(c_1+m_1) \le r^4

证明:

先考虑证明存在整数序列m1,...,mrm'_1,...,m'_r,使得对任意i,j,a,bi,j,a,bmi+cam'_i+c_amj+cbm'_j+c_b在模r3r^3的意义下不同余。

如果我们找到了这样的整数序列,那么所有r2r^2ci+mjc_i+m'_j都是两两不同的,并且由于这个是在模r3r^3意义下两两不同的,所以我们可以对第iici+mic_i+m'_i加上(i1)r3(i-1)*r^3,这样就可以保证对所有ii满足ci+mi<ci+1+mi+1c_i+m'_i<c_{i+1}+m'_{i+1}了。

关于m1,...,mrm'_1,...,m'_r的存在性:

使用数学归纳法来证明,显然我们可以找到m1m'_1,这个平凡。

假设结论对tt成立,即我们已经找到了m1,...,mtm'_1,...,m'_t,满足对任意1i,jt1 \le i,j \le ta,ba,b,有mi+cam'_i+c_amj+cbm'_j+c_b在模r3r^3的意义下不同余。 可以观察到mt+1+cims+cj(modr3  )m'_{t+1}+c_i \equiv m'_s+c_j (\mod r^3\;),即mt+1ms+cjci(modr3  )m'_{t+1} \equiv m'_s+c_j-c_i (\mod r^3\;)

我们可以令mt+1m'_{t+1}[0,r3)[0,r^3)中最小的和所有ms+cjcim'_s+c_j-c_i不同余的数,这里1st,1i,jr1 \le s \le t,1 \le i,j \le r

由鸽巢原理,由于tr2<r3t*r^2<r^3,所以我们一定可以找到mt+1m'_{t+1}

故当t+1st+1 \le s时,结论对t+1t+1成立 由数学归纳法知结论对ss成立,同时我们这里给出了一个暴力的O(r4)O( r^4 )的构造算法(rr轮,每轮最坏枚举O(r3)O( r^3 )个位置)。

5.融合:

融合树的"融合"即指将每个节点上的key放到同一个wbitw-bit的word上,通过对这个word进行运算来一起处理这些key。

沿用之前uiu_iB(S)={ci}B(S)=\{c_i\}的记号:

我们这个B-Tree的每个节点存了C=bin(c1,...cr)C=bin(c_1,...c_r)M=bin(m1,...,mr)M=bin(m_1,...,m_r)这两个量,用于计算u(S)u'(S),同时还存了D=bin(c1+m1,...,cr+mr)D=bin(c_1+m_1,...,c_r+m_r)这个量,用于清空u(S)u'(S)的计算中不需要的位。

同时还需要两个数组,存排序后的uiu_iuiu'_i,和一个表f[i][j][2]f[i][j][2]表示引理11中,如果知道了uiu_ijj,还有uuuiu_i的大小关系,我们唯一确定的答案是多少。

回顾之前的内容,当我们算出了j=rank(K(S),u(S))j=rank(K(S),u'(S))后,如果uu不在[uj,uj+1][u_j,u_{j+1}]的区间中,那么我们把u(S)  XOR  uju'(S) \;\mathrm{XOR}\; u'_ju(S)  XOR  uj+1u'(S) \;\mathrm{XOR}\; u'_{j+1}比较一下,较小的值所对应的uhu'_hh=jh=jj+1j+1,和uu有更长的公共前缀,即msbmsb更小。

m=msb(u,uh)m=msb(u,u_h),然后我们需要知道mm被哪个B(S)B(S)中的区间[ci,ci+1][c_i,c_{i+1}]包含,所以需要进行一次i=rank(B(S),m)i=rank(B(S),m)的计算 还需要进行一次uuuhu_h的比较,这个平凡,当这些都做完了,我们查一下表ff即可得到rank(S,u)rank(S,u)

可以发现fusion tree的每个内部节点需要存下O(B2)O( B^2 )大小的表,内部节点个数是O(n/B4)O( n/B^4 )个,所以是O(n)O( n )空间的。

下面给出对

  1. rank(K(S),u(S))rank(K(S),u'(S))

  2. rank(B(S),m)rank(B(S),m),其中mm是在[0,w][0,w]中的整数

  3. 两个wbitw-bit的整数u,vu,vmsb(u,v)msb(u,v)

的计算方法:

O(1)O(1)计算rank(K(S),u(S))rank(K(S),u'(S))

我们把每个K(S)K(S)中的元素前面补一个11,然后从小到大拼到一起来,这个拼起来的操作就是所谓的"融合"。

由于我们K(S)K(S)中有kk个元素,每个元素有r4r^4位,所以这里总共用了k(r4+1)k(r^4+1)位,由于B/2kBB/2 \le k \le B,所以我们总的位数是O(B5)O( B^5 )的,由于B=O(w1/5)B=O( w^{1/5} ),所以总的位数是O(w)O( w )的。

所以我们拼起来的这个东西是O(1)O( 1 )个word的,这里将其定义为AA

C=i=0B2(r4+1)iC=\sum \limits _{i = 0} ^ {B} 2^{(r^4+1)i} 通过u(S)×Cu'(S) \times C,可以将u(S)u'(S)前面补一个00之后复制BB遍,然后拼到一起 通过Au(S)×CA-u'(S) \times C,可以发现对每个AA中补11的位置,其对应的那个ui(S)u_i(S)如果<u(S)<u'(S),则这个11变成00,否则11不变 所以我们通过(Au(S)×C)&C(A-u'(S) \times C)\&C,然后对这个word数11的个数即可知道rank(K(S),u(S))rank(K(S),u'(S))

由于这个word只在2(r4+1)i2^{(r^4+1)i}这样的位置有11,我们可以通过一次对2r4+112^{r^4+1}-1的取模来得到其中11的个数,虽然对常数取模可以用乘法和位运算O(1)O(1)实现,但我们这里可以给出一个更合适的构造。

我们可以通过将其乘C&(2(r4+1)k1)C \& (2^{(r^4+1)k}-1),这样相当于把其叠加了kk次之后加起来,可以发现其中有一个长为r4+1r^4+1的段,这段的二进制表示的值等于这个word在2(r4+1)i2^{(r^4+1)i}这些位置的元素的和。

通过位移和AND\mathrm{AND}我们可以取出这个长r4+1r^4+1的段,于是就完成了。

答案即$((((A-u'(S) \times C) \& C) \times (C \& (2^{(r^4+1)k}-1))) \& C)>>((k(r^4+1)-1)$

O(1)O(1)计算rank(B(S),m)rank(B(S),m)mm是在[0,w][0,w]中的整数:

由于我们可以O(1)O(1)计算rank(K(S),u(S))rank(K(S),u'(S)),所以把这个查出来然后判断那一个数的大小,并且进行一次查表即可。

O(1)O(1)计算msb(u,v)msb(u,v)

等价于求u  XOR  vu \;\mathrm{XOR}\; v的最高位11的位置,设A=u  XOR  vA=u \;\mathrm{XOR}\; v

我们将AA分为rcr^c大小的块,总共rr块,这里cc是一个常数,c>1c>1C=(100...0100...0......)2C=(100...0100...0......)_2,这里每两个11之间有r1r-111CC是一个常数。

注意到:

((100...0)20)&(1<<(rc)1)=(1<<(rc)1)((100...0)_2-0)\&(1<<(r^c)-1)=(1<<(r^c)-1)

((100...0)2y)&(1<<(rc)1)=0((100...0)_2-y)\&(1<<(r^c)-1)=0,这里y>0y>0

先考虑对每个块去掉首位,块内是否有11

我们用A&CA\& \sim C可以去掉每一块的首位。

然后用C(A&C)C-(A\& \sim C)可以使得每一块中除首位外如果有11,则其在该块首位为00,否则为11

然后用(C(A&C))&C(C-(A\& \sim C))\&C去掉了C(A&C)C-(A\& \sim C)中每一块中除首位外的部分。

然后用(C((C(A&C))&C))(C-((C-(A\& \sim C))\&C))可以得到:如果一块中除首位外有11,则块首位为11,否则为00,且块首位外所有位置都是00的一个数 再考虑对每个块只保留首位,块内是否有11

这个用A&CA\&C即可。

最后(A&C)(C((C(A&C))&C))(A\&C)|(C-((C-(A\& \sim C))\&C))可以得到:如果一块中有11,则块首位为11,否则为00,且块首位外所有位置都是00的一个数。

D=k=0r12k(rc1)D= \sum \limits _{k=0}^{r-1} 2^{k(r^c-1)}

通过$(((A\&C)|(C-((C-(A\& \sim C))\&C))) \times D)>>(w-r)$可以将每块首位的数字拼到一个长rr的二进制数中。

然后我们可以使用前面的O(1)O(1)计算rankrank的方法,令B(S)=2iB'(S)={2^i}ii[0,r1][0,r-1]间,是整数。

通过$rank(B'(S),(((A\&C)|(C-((C-(A\& \sim C))\&C))) \times D)>>(w-r))$就可以得到这个长rr的二进制数中第一个非0的首位的位置了。

我们知道了第一个非00位在哪个块中,然后查这个块里面第一个非00位的位置就可以了。

由于我们每个块是rcr^c的大小,所以对一个大小为rcr^c,包含了2i2^i的集合用一次rank即找到了块内第一个非00的首位位置。

c=4,r=w1/5c=4,r=w^{1/5}rc=w4/5r^c=w^{4/5},我们便O(1)O(1)查询,O(w4/5)O(w^{4/5})预处理时间复杂度解决了这个问题,由于预处理次数是O(n/B4)O( n/B^4 ),所以这里也是线性的。

综上所述,我们得到了一个单次操作复杂度O(logn/logw+logw)O( \log n/\log w + \log w )的数据结构,这里据说可以通过一些优化做到O(logn/logw)O( \log n/\log w ),但在这里由于我还没看所以暂时不做介绍。

6.一些拓展

如果我们允许下列中的一个:

  1. 放松线性空间的限制

  2. 保留线性空间的限制,但是使用随机化和整数除法

那么我们可以得到一个O(logn)O( \sqrt{ \log n } )的动态搜索的时间复杂度上界。

nn超过2(logw)2/362^{(\log w)^2/36}时(这里1/361/36的常数是论文中给出的,由于我的部分细节和论文中不同,可能是不同的常数),

对于1的case,可以通过使用vEB树来实现,对于2的case,可以通过使用Y-fast trie实现。

对于这样的nn,这两个数据结构可以在O(loglogU)=O(logw)=O(logn)O( \log \log U )=O( \log w )=O( \sqrt{\log n} )的时间完成一次搜索操作。

nn小于这个数时,

对于较小的nn,我们使用fusion tree,通过调节B=Θ(2logn)B=Θ(2^ {\sqrt{\log n}})

在这个BB下,我们的时间复杂度是O(logn/logB+logB)=O(logn)O( \log n/\log B + \log B ) = O( \sqrt{\log n} )

综上所述,如果引入随机化和整数除法,可以O(nlogn)O( n \sqrt{\log n} )时间,线性空间整数排序。

7.总结

由信息论可以证明基于比较的排序下界是Ω(nlogn)\Omega( n\log n )的,但整数排序其实是非常复杂的一个问题,还有待研究。

题目描述

魔法森林里有一颗大树,下面经常有小孩召开法。

大树可以看做一个有 nn 个节点,n1n - 1 条边的无向连通图。大树的每个节点都有若干瓶矿泉水,初始第 ii 个节点有 aia_i 瓶矿泉水。

麦杰斯住在大树顶端,有一天他想改造一下大树,方便他巨大多喝水之后可以垃圾分类矿泉水瓶。

麦杰斯喜欢二进制运算,所以他会有以下三种操作:

  1. 将树上与一个节点 xx 距离为 11 的节点上的矿泉水数量 +1+1。这里树上两点间的距离定义为从一点出发到另外一点的最短路径上边的条数。
  2. 在一个节点 xx 上喝掉 vv 瓶水。
  3. 询问树上与一个节点 xx 距离为 11 的所有节点上的矿泉水数量的异或和。

麦杰斯共有 mm 次操作,他希望你在每次 33 操作后告诉他答案。

输入格式

第一行两个正整数 n,mn,m,分别表示树的节点个数和麦杰斯的询问个数。

第二行到第 nn 行,每行两个整数表示有一条连接这两个节点的边。

n+1n + 1nn 个整数,第 ii 个整数表示初始第 ii 个节点上的矿泉水数量。

n+2n + 2 行到第 n+m+1n + m + 1 行,每行先读入一个整数 optopt 表示操作类型。

如果 opt=1opt = 133 ,接下来读入一个整数 xx 表示麦杰斯操作的节点标号。

否则接下来读入两个整数 x,vx, v 表示麦杰斯操作的节点标号和他喝的水的数量。

输出格式

对于每一个 33 操作,输出一行一个整数表示答案。

3 2
1 2
2 3
1 1 4
1 1
3 2
5

提示

Idea:dangxingyu,Solution:dangxingyu,Code:dangxingyu,Data:dangxingyu

对于 30%30\% 的数据,满足 n103n \le 10^3m103m\le 10^3

对于 60%60\% 的数据,满足 n105n \le 10^5m105m \le 10^5

对于另外 10%10\% 的数据,存在一个点满足所有点到该节点的距离 1\le 1

对于 100%100\% 的数据,满足 1n5×1051\le n \le 5\times 10^51m5×1051\le m \le 5\times 10^50ai1050\le a_i \le 10^51xn1 \le x \le nopt{1,2,3}opt\in\{1,2,3\}

保证任意时刻每个节点的矿泉水数非负。

温馨提示:矿泉水瓶不是干垃圾也不是湿垃圾,而是可回收垃圾。