線段樹的應用

2022-05-05 15:03:06 字數 1587 閱讀 1703

標籤(空格分隔): c++ 資料結構

有時候我們求乙個給定的平面直角座標系中的n個矩形的面積,而此時,我們就需要引入一種高效且奇妙的演算法——掃瞄線。

例如該圖:

我們將其中的矩形按上下邊,構建4條掃瞄線,並按照y值大小進行排序,並標記為上或下。

但是由於矩形的x座標有4個,並且相互關聯,而想要提公升演算法效率就必須盡可能規避大的狀態轉移(區間,資訊合併),所以我們將x節點離散化,此時,我們就可以用類似線段樹來維護資訊。

ps:離散化:進行區間對映,並刪除重複(主要用來減少空間大小)

此時,我們用4個不同的x座標把x軸分成了3段有效的區間.這裡要注意我們線段樹中每個葉節點控制的是區間[x[l],x[l+1]].線段樹中其他節點控制的區間[l,r],也是指的x座標軸的第l個區間到第r個區間的範圍,也就是x[l]到x[r+1]座標的範圍。

考慮如何用此時有效的資訊進行最後答案的求值:

1.以y座標從小到大的順序讀入每條掃瞄線

2.記錄當前所讀入的所有掃瞄線能有效覆蓋x軸的最大長度sum[1].

3.用mark[i]記錄線段樹中第i個節點是否被完全覆蓋,以及完全覆蓋次數,當為下位邊+1,上位邊-1。

建議自己進行模擬,感受一下長度的加減與邊上下的關係,同時感受mark的妙用。

建立結構體:(詳情看注釋)

按節點儲存資訊

//以橫座標作為線段(區間),對橫座標線段進行掃瞄

//掃瞄的作用是每次更新下底邊總長度和下底邊個數,增加新面積

struct node

//結構體初始化

node(double x1,double x2,double h,int c):l(x1),r(x2),h(h),d(c){}

//過載運算(相當於cmp)

bool operator

seg(long long x1,long long x2,long long h,int c):l(x1),r(x2),h(h),d(c){}

bool operator

//二分查詢,在已經更新的x中尋找當前掃瞄線左右端點的編號(應該是沒有-1情況的......)

int search(long long key,long long* x,int n)

return -1;}

int main()

//離散化&去重

sort(x,x+k);

sort(s,s+k);

int m=1;

for(int i=1;i

if(x[i] != x[i-1])

x[m++]=x[i];

long long ans=0;

//根據掃瞄線的左右端點更新答案

for(int i=0;i

printf("%lld\n",ans);

return 0;

}

線段樹應用

1 區間最值查詢問題 查詢區間最值下標 min includeusing namespace std define maxn 100 define maxind 256 線段樹節點個數 構建線段樹,目的 得到m陣列.void build int node,int b,int e,int m,int ...

線段樹的基礎應用

大約為葉子節點的4倍 線段樹父節點的資訊可以利用up 從子節點提取的 同時線段樹樹上可以通過down 將父節點的資訊給子節點 void tree int l,int r,int p void build int l,int r,int p 以求區間和為例 void update int x,int ...

Mex(線段樹的巧妙應用)

題目要求求某段區間第乙個沒有出現的數 0,1,2,3.對於所有的區間,我們把這樣的數加起來最後得到乙個結果。首先,我們要求出這樣的數,然後還得列舉出所有的區間,複雜度太大了。換種思路,我們定住l,是不是一次效能求出所有的r所得出的結果,這就用到線段樹的性質了,因為在移動l的過程中,移一步只變化乙個數...