POJ 1151(HDU 1542)Atlanttis【矩形面積及び線分樹+離散化+走査線テンプレート】
Description
The e e are several ancint Greexts texts that contan descriptions of the fabled island Atlant tis.Some of these textseve maps of the island.But unfortunally,these maps describe different regions.Afront.voluntered to write a program that calculates this quantity.
Input
The input consists of several test cases.Each test case starts with a line containing a single integer n(1<=n==100)of available maps.The n following line describe one map each.Each of these line s containtens fourem 1;y 1;x 2;y 2(0<=x 1<=100000;、0<=y 1The input file is terminated by a line containing a single 0.Don't process it.
Output
For each test case、your program shoutputone section.The first line of each sectction must be「Test case\脸k」、where k is the number of the test case(starting with 1).The second onemusbe.The second one mmusbe「Totaltaltaleeeeeex thetaltaltaltaltaltaltrtrtrtrtrtraaaaaaaatrtrtrtrtrtrtrtrtrtrtraaaaaaaaaaaaaaaaaaaaaatrtrtrtrtrtrtrtrtrtrtrtrtrtraaaaaaを選択します.printed exact to two digits to the right of the decimal point.
Output a blank line after each test case.
Sample Input
走査線法:左から右へ(右から左へ)または下から上へ(上から下へ)スキャンした多角形全体(または奇形.複数の長方形を重ねた図形)を想定しています.縦方向のスキャンであれば、離散化横座標であり、水平方向のスキャンであれば離散化縦座標である.以下の解析は横座標を離散化し,下から上へスキャンした.
スキャンする前に、すべての長方形の上の下を保存し、それらの高さによって並べ替えます.また上の方から彼に1つの値をあげます.下の方から1つの値をあげます.構造体ですべての上の下を保存します.
struct segment{double,r,h; //l,rはこの上と下の左右座標を示し、hはこの辺の高さint fである. //与えられた値、1または-1}
次に走査線を下から上にスキャンし、上から下に出会うごとに停止します.この線分を総区間に投影します.この投影は線分を挿入して削除します.彼らに与えられた値の1または-1を覚えていますか?下は1で、下にスキャンすれば、全区間に線分を挿入するのに相当します.上は-1で、上は総区間で線分を削除するのに相当します.(挿入削除が抽象的だというなら、下にスキャンして、全区間に投影して、対応する区間の値は全部1増加して、上にスキャンして対応する区間の値は全部1マイナスになります.総区間のある区間の値が0なら、線分がカバーされていないと説明します.正数であれば、マイナスになりますか?不可能です.自分で考えてみてください.下の方
一つの上の下にスキャンして、全体の区間に投影した後、全区間が現在覆われている全体の長さを判断し、次の辺の高さから現在のこの辺の高さを差し引いて、総区間で覆われている長さに乗ると、一つの面積が得られます.
下のテンプレートは左から右にスキャンされているようです.
The e e are several ancint Greexts texts that contan descriptions of the fabled island Atlant tis.Some of these textseve maps of the island.But unfortunally,these maps describe different regions.Afront.voluntered to write a program that calculates this quantity.
Input
The input consists of several test cases.Each test case starts with a line containing a single integer n(1<=n==100)of available maps.The n following line describe one map each.Each of these line s containtens fourem 1;y 1;x 2;y 2(0<=x 1<=100000;、0<=y 1
Output
For each test case、your program shoutputone section.The first line of each sectction must be「Test case\脸k」、where k is the number of the test case(starting with 1).The second onemusbe.The second one mmusbe「Totaltaltaleeeeeex thetaltaltaltaltaltaltrtrtrtrtrtraaaaaaaatrtrtrtrtrtrtrtrtrtrtraaaaaaaaaaaaaaaaaaaaaatrtrtrtrtrtrtrtrtrtrtrtrtrtraaaaaaを選択します.printed exact to two digits to the right of the decimal point.
Output a blank line after each test case.
Sample Input
2
10 10 20 20
15 15 25 25.5
0
Sample OutputTest case #1
Total explored area: 180.00
このテンプレートはkuangbinから抜粋します.リンクを開くにはクリックしてください.走査線法:左から右へ(右から左へ)または下から上へ(上から下へ)スキャンした多角形全体(または奇形.複数の長方形を重ねた図形)を想定しています.縦方向のスキャンであれば、離散化横座標であり、水平方向のスキャンであれば離散化縦座標である.以下の解析は横座標を離散化し,下から上へスキャンした.
スキャンする前に、すべての長方形の上の下を保存し、それらの高さによって並べ替えます.また上の方から彼に1つの値をあげます.下の方から1つの値をあげます.構造体ですべての上の下を保存します.
struct segment{double,r,h; //l,rはこの上と下の左右座標を示し、hはこの辺の高さint fである. //与えられた値、1または-1}
次に走査線を下から上にスキャンし、上から下に出会うごとに停止します.この線分を総区間に投影します.この投影は線分を挿入して削除します.彼らに与えられた値の1または-1を覚えていますか?下は1で、下にスキャンすれば、全区間に線分を挿入するのに相当します.上は-1で、上は総区間で線分を削除するのに相当します.(挿入削除が抽象的だというなら、下にスキャンして、全区間に投影して、対応する区間の値は全部1増加して、上にスキャンして対応する区間の値は全部1マイナスになります.総区間のある区間の値が0なら、線分がカバーされていないと説明します.正数であれば、マイナスになりますか?不可能です.自分で考えてみてください.下の方
一つの上の下にスキャンして、全体の区間に投影した後、全区間が現在覆われている全体の長さを判断し、次の辺の高さから現在のこの辺の高さを差し引いて、総区間で覆われている長さに乗ると、一つの面積が得られます.
下のテンプレートは左から右にスキャンされているようです.
#include
#include
#include
using namespace std;
#define MAXN 201
struct Node
{
int l,r;//
int c;//c
double cnt,lf,rf;//
//cnt ,rf,lf
}segTree[MAXN*3];
struct Line
{
double x,y1,y2;
int f;
}line[MAXN];
// y ,
//x x ,y1,y2
// , f 1, -1,
// , ,nod c
bool cmp(Line a,Line b)//sort
{
return a.x < b.x;
}
double y[MAXN];// y
void Build(int t,int l,int r)//
{
segTree[t].l=l;segTree[t].r=r;
segTree[t].cnt=segTree[t].c=0;
segTree[t].lf=y[l];
segTree[t].rf=y[r];
if(l+1==r) return;
int mid=(l+r)>>1;
Build(t<<1,l,mid);
Build(t<<1|1,mid,r);//
}
void calen(int t)//
{
if(segTree[t].c>0)
{
segTree[t].cnt=segTree[t].rf-segTree[t].lf;
return;
}
if(segTree[t].l+1==segTree[t].r) segTree[t].cnt=0;
else segTree[t].cnt=segTree[t<<1].cnt+segTree[t<<1|1].cnt;
}
void update(int t,Line e)// e,
{
if(e.y1==segTree[t].lf&&e.y2==segTree[t].rf)
{
segTree[t].c+=e.f;
calen(t);
return;
}
if(e.y2<=segTree[t<<1].rf) update(t<<1,e);
else if(e.y1>=segTree[t<<1|1].lf) update(t<<1|1,e);
else
{
Line tmp=e;
tmp.y2=segTree[t<<1].rf;
update(t<<1,tmp);
tmp=e;
tmp.y1=segTree[t<<1|1].lf;
update(t<<1|1,tmp);
}
calen(t);
}
int main()
{
int i,n,t,iCase=0;
double x1,y1,x2,y2;
while(scanf("%d",&n),n)
{
iCase++;
t=1;
for(i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[t].x=x1;
line[t].y1=y1;
line[t].y2=y2;
line[t].f=1;
y[t]=y1;
t++;
line[t].x=x2;
line[t].y1=y1;
line[t].y2=y2;
line[t].f=-1;
y[t]=y2;
t++;
}
sort(line+1,line+t,cmp);
sort(y+1,y+t);
Build(1,1,t-1);
update(1,line[1]);
double res=0;
for(i=2;i