题意:
求矩形面积的并
解题思路:
先将x坐标离散化,扫描线从底向上扫描。所以通过步骤,我们只记录平行与x走的线段,定义结构体
struct segment{
int l,r,h;// l表示该选段的左坐标,r表示该线段的有坐标,h表示改线 段的高度
bool flag;//表示该线段是所在矩形的上边还是下边
};
所以我们根据线段的h轴进行从小到大排序,遇到下边对将对应的区间[l,r-1]更新导线段树中
我们用[l,r-1]来取代[l,r]来进行保存因为我们这里保存的是一段距离
,所以线段树的某一个节点表示的意思是该dis[节点.R+1] - dis[该节点.L ],这样返回的就是当前矩形x坐标覆盖的总距离。
注意:
无
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define MAXN0 500
#define eps 1e-8
#define l1(x) (x)<<1
#define r1(x) (x)>>1
int dcmp(double x);
struct segment{
double l,r,h;
bool flag;
void set(double ll,double rr,double hh,bool ff){
l = ll;
r = rr;
h = hh;
flag = ff;
}
friend bool operator<(segment aa,segment bb){
int tmp0 = dcmp(aa.h - bb.h);
return tmp0<0;
}
};
struct TRnode{
int L,R;
int c,num;
double Len;
};
TRnode TR[MAXN0<<2];
segment seg[MAXN0];
double x[MAXN0];
int cntx,cnts;
int dcmp(double x){
if(fabs(x)<eps){
return 0;
}
return x<0?-1:1;
}
int cmp(double aa,double bb){
return dcmp(aa-bb)<0;
}
void buildTR(int L,int R,int k){
TR[k].L = L;
TR[k].R = R;
TR[k].Len = 0;
TR[k].num = 0;
TR[k].c = -1;
if(L==R)return;
int k1,k11,mid;
k1 = l1(k);
k11 = k1 + 1 ;
mid = r1(L+R);
buildTR(L, mid, k1);
buildTR(mid+1,R,k11);
}
//void pd(int k,int k1,int k11){
// TR[k1].c = TR[k11].c = TR[k].c;
// if(TR[k].c==0){
// TR[k1].Len = TR[k1].R - TR[k1].L + 1;
// TR[k11].Len = TR[k11].R - TR[k11].L + 1;
// }
// else {
// TR[k1].Len = 0;
// TR[k11].Len = 0;
// }
// TR[k].c = -1;
//}
void pu(int k,int k1,int k11){
if(!TR[k].num)
TR[k].Len = TR[k1].Len + TR[k11].Len;
}
void update(int L,int R,int k,bool w){
if(TR[k].L==L&&TR[k].R==R){
if(w==0){
if(!TR[k].num){
TR[k].Len = x[R] - x[L-1];
}
TR[k].num++;
}
else {
--TR[k].num;
if(TR[k].num==0){
int k1,k11;
k1 = l1(k);
k11 = k1+1;
pu(k,k1,k11);
}
}
return;
}
int k1,k11;
k1 = l1(k);
k11 = k1 + 1;
// if(TR[k].c>-1){
// pd(k,k1,k11);
// }
int mid = r1(TR[k].L+TR[k].R);
if(mid>=R){
update(L,R,k1,w);
}
else if(mid<L){
update(L,R,k11,w);
}
else{
update(L,mid,k1,w);
update(mid+1,R,k11,w);
}
pu(k,k1,k11);
}
double query(int k){
return TR[k].Len;
}
void prepro(){
sort(x,x+cntx,cmp);
int tcnt = 0;
x[tcnt++] = x[0];
for(int i=1;i<cnts;++i){
if(!dcmp(x[i]-x[i-1]))continue;
x[tcnt++] = x[i];
}
cntx = tcnt;
sort(seg,seg+cnts);
buildTR(1, cntx, 1);
}
int bin(double xg){
int L = 0,R = cntx - 1;
int mid,tmp0;
while(L<R){
mid = r1(L+R);
tmp0 = dcmp(x[mid] - xg);
if(!tmp0){
return ++mid;
//break;
}
if(tmp0>0){
R = mid;
}
else{
L = L+1;
}
}
return ++L;
}
double solve(){
int i=0;
int up = cnts - 1;
double area = 0;
int tmp0;
double tmp1;
int L,R;
double len = 0;
while(i<up){
tmp0 = dcmp(seg[i+1].h - seg[i].h);
L = bin(seg[i].l);
R = bin(seg[i].r);
if(!tmp0){
update(L,R-1,1,seg[i].flag);
}
else {
update(L,R-1,1,seg[i].flag);
double H = seg[i+1].h - seg[i].h;
area = area + H*query(1);
}
++i;
}
return area;
}
int main(){
int n;
int cas = 0;
double x1,x2,y1,y2;
while(scanf("%d",&n)!=EOF){
if(!n)break;
cntx = 0;
cnts = 0;
for(int i=0;i<n;++i){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
x[cntx++] = x1;
x[cntx++] = x2;
seg[cnts++].set(x1,x2,y1,false);
seg[cnts++].set(x1,x2,y2,true);
}
prepro();
double area = solve();
printf("Test case #%d\n",++cas);
printf("Total explored area: %.2lf\n\n",area);
}
return 0;
}