講解的很生動。
分析:
首先我們將矩形的上下邊分為上位邊(即y座標大的那條平行於x軸的邊),和下位邊(y座標小的平行於x軸的邊).然後我們把所有矩形的上下位邊按照他們y座標從小到大排序;
需要把x座標離散化,這樣才能用線段樹來維護資訊.所謂離散化,就是將元素排序,去重,這樣得到乙個陣列a,這個陣列就是建立線段樹的關鍵;
主要知識:
關於線段樹:線段樹的葉節點([l,r],這裡l==r,指的是建立線段樹陣列中的下標),線段樹中葉節點代表的都是某乙個陣列的下標,其他節點則是多個下標。
建立乙個線段樹必須要有乙個陣列,根據其座標建立線段樹。本題中葉節點控制的[l,l]實際上代表的是[ a[l],a[l+1] ].線段樹中其他節點控制的區間[l,r],也是指的x座標軸的第l個區間到第r個區間的範圍,也就是x[l]到x[r+1]座標的範圍.
關於離散化:
離散化就是壓縮區間,使原有的長區間對映到新的短區間,但是區間壓縮前後的覆蓋關係不變,本題中離散化就是把矩形端點的x座標放進乙個陣列中,去掉重複的座標。,這就用到了unique函式。
關於unique函式:
unique()函式是乙個去重函式,stl中unique的函式 unique的功能是去除相鄰的重複元素(只保留乙個),還有乙個容易忽視的特性是它並不真正把重複的元素刪除。之所以說比不真正把重複的元素刪除,其實是,該函式把重複的元素一到後面去了,然後依然儲存到了原陣列中,返回值是相互間不相同的個數,注意用這個函式之前需要排序。
**如下:
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
//掃瞄線,也就是矩形的和x軸平行的那些邊,記錄高度和左右端點座標,和
class seg
};bool cmp(seg p,seg q)
const
int maxn=100+5;
seg seg[maxn<<1];
double cnt[maxn<<3],sum[maxn<<3];//cnt表示當前區間狀態,0表示被覆蓋,大於零則被掃瞄,sum代表區間長度
double x[maxn<<1];
//建樹,
void build(int l,int r,int rt)
//注意[l,r]間的長度是x[r+1]-x[l]
void push_up(int l,int r,int rt)
//更新,如果是上位邊則加一,下位邊減一
void update(int ll,int rr,int c,int l,int r,int rt)
int m=(l+r)>>1;
if(ll<=m)update(ll,rr,c,l,m,rt<<1);
if(rr>m)update(ll,rr,c,m+1,r,rt<<1|1);
push_up(l,r,rt);
}int main()
build(0,numx-2,1);
sort(x,x+numx);
sort(seg,seg+nums,cmp);
numx=unique(x,x+numx)-x; //離散化
double res=0;
//讓每一條掃瞄線掃瞄
for(int i=0;i1;i++)
printf("test case #%d\n",++kase);
printf("total explored area: %.2lf\n\n",res);
}}
線段樹求矩形面積並 掃瞄線 離散化
顧名思義,掃瞄法就是用一根想象中的線掃過所有矩形,在寫 的過程中,這根線很重要。方向的話,可以左右掃,也可以上下掃。方法是一樣的,這裡我用的是由下向上的掃瞄法。如上圖所示,座標系內有兩個矩形。位置分別由左下角和右上角頂點的座標來給出。上下掃瞄法是對x軸建立線段樹,矩形與y平行的兩條邊是沒有用的,在這...
線段樹求矩形面積並 掃瞄線 離散化
顧名思義,掃瞄法就是用一根想象中的線掃過所有矩形,在寫 的過程中,這根線很重要。方向的話,可以左右掃,也可以上下掃。方法是一樣的,這裡我用的是由下向上的掃瞄法。如上圖所示,座標系內有兩個矩形。位置分別由左下角和右上角頂點的座標來給出。上下掃瞄法是對x軸建立線段樹,矩形與y平行的兩條邊是沒有用的,在這...
Atlantis(線段樹掃瞄線求面積)
output a blank line after each test case.這裡看到我寫了兩次並且兩次都用了粗體,就應該知道我wa在 了吧。坑哭了,沒看到這細節。還有乙個就是要注意這個是多組樣例的,所以千萬要記得tree陣列要初始化。我和其他人的寫法不太一樣,因為按點寫線段我實在理解不了,也不...