西安段素掃瞄線

2022-04-30 01:21:15 字數 1825 閱讀 7327

如果我們要統計乙個由多個矩形重疊組成的圖形的面積。

暴力太麻煩,而計算機又不能想人一樣計算,那怎麼求解呢?

我們可以使用掃瞄線fa

想象一下,有一條線,按照乙個順序(從左到右呀,從上到下呀...)掃瞄乙個圖形。

我們很容易可以得到,兩條最近的相鄰線段間,所包含的這乙個圖形的面積是規整的矩形,又因為這些矩形的長or寬我們已經知道(就是資料中給定矩形的邊),所以我們只需要統計另一條邊就可以了。

維護線段,我們就可以使用西安段素了。

同乙個矩形,在遇到他的第一條和掃瞄線(是乙個線段樹)平行的的邊時,在這條邊和掃瞄線重疊的部分上累加1(一定是累加),然後繼續往後掃瞄,遇到其他矩形的第一條邊時亦是。

知道碰到某個矩形的第二條邊,在減去。

那在掃瞄中怎麼算面積呢? 我們需要統計的是掃瞄線上有多少長度被覆蓋,然後乘上兩條線段之間的垂直距離就可以了。

那統計周長怎麼算呢?

(現在都是從下往上掃)先來看平行於掃瞄線的邊。

兩次掃瞄後,掃瞄線上的被覆蓋長度的差的絕對值就是所增加的長度。

為什麼是差呢?又為什麼是絕對值呢?

我們通過一張圖來解釋:

可以看出,這是兩個矩形巢狀,然後自己在寬扁的矩形的左邊第一條邊的掃瞄線上的被覆蓋的長度,和另乙個矩形的第一條邊時的差就是第二個矩形延展出來的長度,然後絕對值的意思是當乙個矩形結束時,他有可能會與他有重疊的矩形凹陷,然後絕對值就將這種情況的邊取了出來。

那於掃瞄線垂直的呢?

我們可以發現,兩次掃瞄中間的那些與掃瞄線垂直的線段,他的長度都是兩次掃瞄之間的距離,然後我們就需要統計他的個數

可以發現, 兩次掃瞄中,有多少個不相連的空隙,就有相同個數*2條如此線段

然後具體實現會從詳解。請先從main()看起

#include#include#includeusing namespace std;

const int manx=5010;

struct edge

};struct node

;int te,tx,k;

edge line[manx<<1];

int base[manx<<1];

int datx[manx<<1];

node t[manx<<5];

void add(int a,int b,int c,int d)

bool compare(const edge &a,const edge &b)

void make_base()

//簡簡單單的去重

return ;

}void build(int root,int l,int r)

int check(int val)

int mid=(l+r)>>1;

updata(root<<1,l,mid,al,ar,k);

updata(root<<1|1,mid+1,r,al,ar,k);

push_up(root,l,r);//合併,這裡沒有push_down

}int main()

sort(line+1,line+1+te,compare);//排序,有重邊一定要下邊先被處理

sort(datx+1,datx+1+tx);//離散化

make_base();//真離散化

build(1,1,k-1);//建樹,注意k為離散化後的座標個數,這裡要建立k-1個葉子節點,線段樹中存的是相鄰兩個座標之間的間隙

int ans=0; //周長

int last=0;//用於記錄兩次掃瞄的被覆蓋的長度的變數

for(int i=1;i<=te;i++)

printf("%d",ans);

}

P5490 模板 掃瞄線 掃瞄線

題目描述 求 n 個矩形的面積並。輸出格式 一行乙個正整數,表示 n 個矩形的並集覆蓋的總面積。発生 線段樹開小了,因為n變成了兩倍,線段樹就得開4 2 8倍 對每一根掃瞄線,維護所截得的長度,每次乘以兩根掃瞄線高度差就得到了面積並 截得長度用線段樹維護即可 注意線段樹需要離散化 include i...

掃瞄線入門

聽說掃瞄線很牛掰,於是就見識了一下。之前做過一道掃瞄線的題,brother,就是判斷矩形是否被矩形內部的車攻擊到。當時是把矩形拆成出邊和入邊 豎直的 把所有小於x2的車加進圖中,掃 y1,y2 中x最小的車的x.和x1判斷比較。然後交換x,y掃一遍 當時只是感覺線段樹很神奇,還可以這樣搞,後來才知道...

模板 掃瞄線

矩形有重疊,求總面積。橫縱兩條掃瞄線 includeusing namespace std double x 2002 y 2002 最多100個矩形,所以最多只有200條橫線或縱線 double a 1002 4 矩形實際座標,分別是左下角橫 縱,右下角橫 縱 bool cover 2002 20...