區間最值問題:
有如下無序序列,求任意子區間段的最大值。
接著,我們要用分治的思想來快速地解決上面的問題。在解決問題之前,先介紹一些分治的概念。
二分查詢
二分查詢是分治思想的典型運用
我們有如下序列:
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 標記時節點實...