掃瞄線演算法+線段樹維護簡介:
像這種求面積的並集的題目,就適合用掃瞄線演算法解決,具體來說就是這樣
類似這種給出點的矩形的對角的點的座標,然後求出所有矩形面積的交集的問題,可以採用掃瞄線演算法解決。圖如下,我們要求紅色部分的面積:
我們可以通過一條叫掃瞄線的東西解決問題。具體來說:
我們首先給自己一條線,這條可以我稱之為標準線(棕色線表示
從上往下(從下往上也行)我們把每個矩形用乙個四元組表示了l,r,h,f 也就是說,把乙個矩形用上下兩條邊表示,
l,r分別是
x1,x2,而h
則是y座標,f
代表這條線是頂邊還是低邊。
這樣就把資訊儲存下來。
需要注意的一點是,由於線段樹維護區間的時候,會存在區間過大的清空,因此我們需要對x座標進行去重排序,從而達到把點進行離散化,但是這裡我們需要注意的是,我們這裡維護區間,而線段樹是從維護點,進而維護區間的,因此我們可以這樣,把區間的左下標表示為區間,比如
[0-3]
區間,我們可以轉化為點
0,代表
0-1,1代表
1-2,2代表
2-3。這樣我們再找左端點的時候,我們之間用座標代替,而右端點,則需要查詢到下標後,減一即可。
維護總的區間的和,用高度差乘以區間和,就是面積,每次維護,求出面積,就是如上圖所示的樣子,從下往上不斷求出面積。
#include#include#include
#include
using
namespace
std;
inline
int l(int r);
inline
int r(int r);
inline
int mid(int l,int r);
const
int maxx = 111
;struct
segmentss[maxx*2
];struct
nodetree[maxx
<<3
];double pos[maxx*2
];int
nums;
bool
cmp(segment p,segment q)
void build(int root,int l,int
r)void get_len(int
root)
void update(int root,int l,int r,int
val)
int mid = (tree[root].l + tree[root].r)>>1
;
if (r<=mid)
update(l(root),l,r,val);
else
if (l >mid)
update(r(root),l,r,val);
else
get_len(root);
}int binary(double key,int low,int
high)
return -1;}
intmain()
sort(ss,ss+nums,cmp);
sort(pos,pos+nums);
int m = 1
;
for (int i=1;i//
離散去重
if (pos[i]!=pos[i-1
]) pos[m++]=pos[i];
memset(tree,
0,sizeof
(tree));
build(
1,0,m-1);//
離散區間就是[0,m-1]
//for (int i=0;i<=m*4+2;i++)
double ans = 0
;
for (int i=0;i1;i++)
printf(
"test case #%d\n
", ++case);
printf(
"total explored area: %.2f\n\n
", ans);
} return0;
}
hdu1542(線段樹 掃瞄線)
裸的掃瞄線,學習掃瞄線的題目。具體掃瞄線的原理我不講了,我是看大神們的部落格懂得,就算寫也沒大神屌。下面我給出我的 裡面的注釋是我認為比較重要的地方 include include include includeusing namespace std const int max 210 int n ...
hdu 1542 掃瞄線 線段樹
題目大意 求矩形面積的並 思路 按y軸排序,然後將x投影到線段樹上做乙個線段覆蓋問題即可 注意 為了避免重複,線段座標右端點是開區間,更新時需要加上1 include include include include include define fo i,a,b for int i a i b i ...
hdu1542(線段樹 掃瞄線)
題目連線 又看到了幾個月前做的題,感覺那時候就是個sb 也怪自己剛開始沒搞清楚線段樹,瞎摸索 用連續線段樹很好理解這個題,之前的 稍微改了一下就好理解多了 1 include2 include3 include4 define lson l,m,rt 1 5 define rson m,r,rt 1...