區間最值與線段樹

2021-06-18 12:58:59 字數 2701 閱讀 8163

區間最值問題:

有如下無序序列,求任意子區間段的最大值。

接著,我們要用分治的思想來快速地解決上面的問題。在解決問題之前,先介紹一些分治的概念。

二分查詢

二分查詢是分治思想的典型運用

我們有如下序列:

a1,a2,a3……an.

要查詢其中等於b的元素。一種方法就是乙個個對比,看看是不是相等,時間複雜度為n。還有就是二分查詢。

如上圖,通過不斷地與中間元素對比,縮小搜尋區間,最後得到a4==b.時間複雜度為logn.

二叉搜尋樹

在二分查詢中,我們要求佇列是有序地。那麼如果佇列無序又要如何?我們可以仿造二分查詢的方式,構造乙個二叉搜尋樹,如下:

二叉搜尋樹左節點比根小,右節點比根大。上圖紅色箭頭代表搜尋a4的過程。

線段樹

線段樹也是一種二叉搜尋樹,我們回到區間最值的問題,有如下無序序列

現在我們要在上面的序列中,搜尋任意指定區間的最大值。

我們先來解決總的最大值的問題

乙個基本的方法就是乙個個比較,取出最大值,時間複雜度為n。

上面的過程就是選取區間最大值的方式,總的最大值為9.

接著,我們要處理任意指定子串行的最值問題。

根據上圖我們可以看出,根據中間的結果,可以和容易地尋找1-6個節點的最大值,分治為1-4的最大值7,5-6的最大值8,1-6的最大值就為8.

總結一下上述的思想。

首先,有點像**選舉,我們要尋找乙個國家最適合當**的人,不需要乙個個去比較,只需要每個鄉選乙個最好的,再在縣里比較,得出乙個縣里最好的,然後市,然後省,最後我們得到了全國最好的。

然後,我們選舉的過程中,得到了鄉,縣的中間結果,這些又可以用來選取任意小範圍的最好人選。如我們要選總管廣東,廣西和南京鼓樓區第二大街的總管,只需要用到不同級別的中間結果彙總即可。

線段樹最終回到分治的思想上來,其應用與如下領域:

區間最值查詢問題

連續區間修改或者單節點更新的動態查詢問題 

多維空間的動態查詢

線段樹的程式設計實踐

線段樹的節點結構為:

struct node

;

其中max儲存當前線段的最大值。

線段樹最基本要有三個函式:

1.遞迴地建立樹:

void buildtree(int index,int left,int right)

int mid=(left+right)>>1;

buildtree((index<<1)+1,left,mid);

buildtree((index<<1)+2,mid+1,right);

return;

}

2.遞迴地插入:

void insert(int index,int left,int right,int k)

if (right<=mid)

else

if (left>mid)

}

3.遞迴地查詢:

int query(int index,int left,int right)

if (right<=mid)

else

if (left>mid)

else

}

最後,求解任意區間最值的**如下:

#includeusing namespace std;

#define maxn 1001

int n,q;

int m(int a,int b)

struct node

;struct node tree[maxn*4];

void buildtree(int index,int left,int right)

int mid=(left+right)>>1;

buildtree((index<<1)+1,left,mid);

buildtree((index<<1)+2,mid+1,right);

return;

}void insert(int index,int left,int right,int k)

if (right<=mid)

else

if (left>mid)

}int query(int index,int left,int right)

if (right<=mid)

else

if (left>mid)

else

}int main()

cin>>q;

while(q--)

{cin>>left>>right;

cout<

線段樹,區間最值

codeforces 91b queue 線段樹,區間最值 題意是,對於給定區間內的每個元素,要求求出離他最遠的那個元素之間的距離。可以維護乙個線段樹的最小值,每次對於乙個元素,查詢其最右邊的元素的位置。include include include includeusing namespace s...

動態區間最值(RMQ) 線段樹

建樹 a aa陣列為初始陣列,tre etree tree 陣列為樹 typedef long long ll const int inf 0x7fffffff const int maxn 2e5 10 int a maxn int tree maxn 2 lz maxn 2 建樹函式 和普通線段...

區間歷史最值筆記 線段樹

cpu監控 要你維護對序列上的操作 1 區間加 2 區間賦值 3 區間最大值 4 區間歷史最值 使用線段樹 標記維護,記錄節點上發生的所有事件。注意到乙個線段樹節點,如果進行了modify操作,那麼接下來的加法都可以認為是modify。那麼乙個節點上的標記長度就至多為2了。設 text 標記時節點實...