以前一直沒仔細學一波掃瞄線,最近終於補了一下。
大致的思想:將座標的一維離散化,然後建立線段樹,維護當前被覆蓋的線段長度,然後將另一維排序,按順序插入線段樹。對於乙個矩形的上底邊和下底邊,(如果從下往上掃瞄)則對下底邊作+1標記,上底邊作-1標記。用乙個結構體儲存一條邊的資訊,包括l:線段左端點,r:線段右端點,h:線段的高度,d:線段的上下底邊標記。線段樹的乙個細節是,每個節點代表的是第幾段線段,而不是某個線段的端點,所以線段[l,r]代表的是第l段線段到第r段線段,
其真實長度=v[r+1]-v[l];(其中v陣列是離散化陣列) 每次兩線段之間的面積就是兩線段高度差*x軸方向覆蓋的線段長度。
#include
using namespace std;
#define maxn 100005
#define ll long long int
#define inf 0x3f3f3f3f
int n,m;
struct node};
node a[maxn<<1]
;vector<
double
>v;
int tot;
int cnt[maxn<<2]
;double sum[maxn<<2]
;void
pushup
(int x,
int l,
int r)
void
update
(int x,
int l,
int r,
int lp,
int rp,
int s)
int mid=
(l+r)
>>1;
if(lp<=mid)
update
(x<<
1,l,mid,lp,rp,s);if
(mid+
1<=rp)
update
(x<<1|
1,mid+
1,r,lp,rp,s)
;pushup
(x,l,r);}
intmain()
; a[
++tot]=;
v.push_back
(x1)
; v.
push_back
(x2);}
sort
(v.begin()
,v.end()
);sort
(a+1
,a+tot+1)
;int len=
unique
(v.begin()
,v.end()
)-v.
begin()
;double ans=0;
for(
int i=
1;i<=tot;i++
)printf
("%lf\n"
,ans)
;return0;
}
模板題,給定n個矩形,求覆蓋的總面積。注意格式,每次輸出之後要跟乙個換行。
#include
.h>
using namespace std;
#define maxn 205
#define ll long
long
int#define inf 0x3f3f3f3f
int n;
struct node
}a[maxn<<1]
;int tot;
vector<
double
>
v;int cnt[maxn<<2]
;double sum[maxn<<2]
;void
pushup
(int x,
int l,
int r)
void
update
(int x,
int l,
int r,
int lp,
int rp,
int s)
int mid=
(l+r)
>>1;
if(lp<=mid)
update
(x<<
1,l,mid,lp,rp,s);if
(mid+
1<=rp)
update
(x<<1|
1,mid+
1,r,lp,rp,s)
;pushup
(x,l,r);}
intmain()
; a[
++tot]=;
v.push_back
(x1)
; v.
push_back
(x2);}
sort
(v.begin()
,v.end()
);sort
(a+1
,a+tot+1)
;int len=
unique
(v.begin()
,v.end()
)-v.
begin()
;double ans=0;
for(
int i=
1;i<=tot;i++
)printf
("test case #%d\n"
,++kase)
;printf
("total explored area: %.2lf\n\n"
,ans);}
return0;
}
題意如圖:
然後對於sum[x][0]的更新也要仔細討論。詳細見**。
///覆蓋兩次以上的面積
#include
using namespace std;
#define maxn 2005
#define ll long long int
#define inf 0x3f3f3f3f
int n,t;
struct node
}a[maxn<<1]
;int tot;
vector<
double
>v;
int cnt[maxn<<2]
;double sum[maxn<<2]
[2];
void
pushup
(int x,
int l,
int r)
else
else}}
}void
update
(int x,
int l,
int r,
int lp,
int rp,
int s)
int mid=
(l+r)
>>1;
if(lp<=mid)
update
(x<<
1,l,mid,lp,rp,s);if
(mid+
1<=rp)
update
(x<<1|
1,mid+
1,r,lp,rp,s)
;pushup
(x,l,r);}
intmain()
; a[
++tot]=;
v.push_back
(x1)
; v.
push_back
(x2);}
sort
(v.begin()
,v.end()
);sort
(a+1
,a+tot+1)
;int len=
unique
(v.begin()
,v.end()
)-v.
begin()
;double ans=0;
for(
int i=
1;i<=tot;i++
)printf
("%.2lf\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...