笛卡爾樹的妙用
阿新 • • 發佈:2018-04-08
兩個 進棧 二叉 clas sta 擁有 logs 查找 一個
前言
笛卡爾樹,其實是一顆treap,每個節點擁有兩個值,key值和val值。key值是這個節點本身的大小值,在一顆treap中滿足二叉查找樹的性質,而val值則是一個隨機值,學過treap的同學都知道,這個val值是拿來使得樹的層高是期望log的,val值滿足堆的性質,這裏以小根堆為例講解(當然大根堆不會有任何問題)。
應用
一般笛卡爾樹都被用來建一顆treap,復雜度為O(n)的,n表示插入的元素個數。
而暴力插入的話是O(n log n)的。
這裏需要講清楚的是,笛卡爾樹建樹,插入的元素必須保證key值遞增,而val值是可以亂的,許多博客裏沒有講,這裏必須要強調一下。
實現
我們維護笛卡爾樹的極右鏈,就是根,根的右兒子,根的右兒子的右兒子.......
放在一個棧裏,棧底是根,這樣很顯然從棧頂到棧底,val值是不斷變小的。
每當我們進入一個新的節點,我們從棧頂開始找,當找到第一個節點的val值比我小,那麽我必須得是它的兒子,而我的key值又比他大,所以我作為它的右兒子,而原先它的右兒子key值比我小,所以作為我的左兒子,這樣就維護了一個treap的性質,然後原來那些點變為了我的左兒子,所以就要從極右鏈中刪掉,我加入到極右鏈中,這樣每個點進棧一次,出棧一次,復雜度就是O(n)的,下面貼出具體的代碼。
for (int i=1;i<=n;i++){ read(key[i]),val[i]=rand(); while (top&&val[i]<val[stack[top]]){ rson[stack[top]]=last; last=stack[top]; lson[i]=stack[top]; top--; } if (top) rson[stack[top]]=i; stack[++top]=i; }
以上就是笛卡爾樹線性建treap的全部過程,希望對大家的學習有幫助
笛卡爾樹的妙用