最近學習了一下劃分樹,下面總結一下。
我們在求區間最值的時候,一般可以用線段樹解決,但是如果要求區間第k小或者第k大值的話線段樹就有點力不從心了,這是我們可以用劃分樹來解決。劃分樹利用了快速排序的思想,首先是建樹,我們設當前區間的中位數為mid,(為了能快速找到區間的中位數,我們一般先對原序列做一次排序)則我們將區間中比mid小的放入左子樹,將區間中比mid大數的放入右子樹中,和mid相等的要討論一下,有些需要放到左子樹中,其他的放到右子樹中,注意我們將數字放入子樹的時候其相對順序是不變的
。這樣我們一層一層下去,每次區間都減半,則空間消耗為o(nlogn)。下面看乙個例子。
假設序列長度為9,依次為 3 5 7 3 4 9 4 2 5,怎我們看看建樹完成後是什麼樣子。
sort[ ][2 3 3 4 4 5 5 7 9]
tree[0][3 5 7 3 4 9 4 2 5]
tree[1][3 3 4 4 2][5 7 9 5]
tree[2][3 3 2][4 4][5 5][7 9]
tree[3][3 2][3][4][4][5][5][7][9]
tree[4][2][3][3][4][4][5][5][7][9]
好了,樹建完了,接下來就是最關鍵的查詢了,我們設函式query(p,l,r,s,t,k)表示在第p層子樹區間範圍在[l,r]的子樹中查詢區間[s,t]中的第k小值。我們在每一顆子樹中設sum[i]表示區間[l,i]範圍內有多少個數字被放到了左子樹中,那麼我們容易得到,sum[t]-sum[s-1]表示在區間
[s,t]有多少個樹被放入了左子樹中,我們不妨設這個值為num,若k<=num,我們就可以知道我們要找的數一定在左子樹中,否則一定在右子樹中,我們接下來只要繼續往下遍歷,當l==r的時候我們就可以確定我們要找的數,容易知道這一步驟的複雜度為o(log n),現在關鍵的一點就是如何再往下便利的時候確定ls,t的值。這個其實自己畫畫圖就很容易推出來的,下面只寫結論,這裡先設區間[l,s-1]中被放入左子樹的數有snum個,當前區間的中點為mid,
則若k<=num,我們返回query(p+1,l,mid,l+snum,l+sum[t]-1,k),(要找的數在左子樹上)
否則,我們返回query(p+1,mid+1,r,mid+1-l+s-snum,mid+1-l+t-sum[t],k-num
);(要找的數在右子樹上)
下面再舉個例子,數和上面一樣
我們現在要找到區間[2,7]中的第3小數。
sort[ ][2 3 3 4 4 5 5 7 9]
tree[0][3 5 7 3 4 9 4 2 5]
tree[1][3 3 4 4 2][5 7 9 5]
tree[2][3 3 2][4 4][5 5][7 9]
tree[3][3 2][3][4][4][5][5][7][9]
tree[4][2][3][3][4][4][5][5][7][9]
以上橙黃色背景的數字即為我們要求的範圍。
我們首先在第一層樹上尋找,即query(0,1,9,2,7,3),我們發現在[2,7]區間中有3個數被放入了左子樹,滿足k<=num,所以我們往左子樹中找,呼叫query(1,1,5,2,4,3)。
在第二層樹中我們發現區間[2,4]只有乙個數被放入左子樹,所以我們要找的數一定在右子樹中,呼叫query(2,4,5,4,5,2)。
在第三層樹中,我們發現區間[4,5]只有乙個數被放入左子樹,同理我們應該往右子樹找,呼叫query(3,5,5,5,5,1)。現在可以發現l==r,則我們可以確定已經找到了要找的數,則返回4即可,我們可知在區間[2,7
]上第3小的數為4。
基礎的劃分樹就到這裡,下面給出我的**:
#include #include #include #include #define maxn 100010
#define mid ((l+r)>>1)
using namespace std;
int t[20][maxn],sum[20][maxn];
int a[maxn],as[maxn];
//以下為查詢區間第k小劃分樹
void build(int p,int l,int r)
for(i=l;i<=r;i++)
else
t[p+1][rs++]=t[p][i];
}else if(t[p][i]下面是兩道劃分樹的模板題
poj 2104
題解這裡有
hdu 4417
題解這裡有:
資料結構 劃分樹小結
劃分樹是一種基於線段樹的資料結構。主要用於快速求出 在log n 的時間複雜度內 序列區間的第k大值。先看下圖已經建好的劃分樹是什麼樣子的,原始陣列是 1,5,2,3,6,4,7,3,0,0 並把它作為樹的第0層,然後把這些數中較小的數再組成 1,2,3,0,0 順序還是遵照原陣列的順序,同樣將較大...
整數劃分(小結劃分數如何dp)
原 小結劃分數如何dp 1.hdu 1028 整數劃分 首先,我們引進乙個小小概念來方便描述吧,dp n m 是把自然數劃劃分成所有元素不大於m的分法,例如 當n 4,m 1時,要求所有的元素都比m小,所以劃分法只有1種 當n 4,m 2時,只有3種,當n 4,m 3時,只有4種,當n 4,m 5時...
劃分樹詳解
題目 給出n個數,和m個區間 對於每個區間 l r 輸出這個區間裡面第k大的數。我們來看看劃分樹是怎麼構造的。構造 以2104為例子,舉2 0 6 8 5 1 4 3 9為例子,構造劃分樹是這樣的 上面的內容是用乙個二位陣列val儲存下來的,第一維表示劃分樹的第幾層,第二位表示在這一層中的位置。要注...