/*
在這裏將一個一個的矩形分隔成兩條平行X軸的線,
在下面一條標記爲正邊,上面一條標記爲負邊。
cnt表示的次節點被覆蓋的次數。
sum表示區間一次覆蓋以上的長度
len表示區間二次覆蓋以上的長度
*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 2222
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid (l+r)>>1
double X[maxn<<2],sum[maxn<<2],len[maxn<<2];
int cnt[maxn<<2];
struct Seg{
double l,r,h;
int c;
Seg(){};
Seg(double t1,double t2,double t3,int t4) :l(t1),r(t2),h(t3),c(t4){}
bool operator < (Seg& cmp){
return h<cmp.h;
}
}seg[maxn<<2];
void Pushup(int l,int r,int rt){
if(cnt[rt])
sum[rt] = X[r+1]-X[l];//實際長度時往開區間移
else if(l == r)
sum[rt] = 0;
else
sum[rt] = sum[rt<<1]+sum[rt<<1|1];
}
void Pushupagain(int l,int r,int rt){
if(cnt[rt]>=2) //如果已經兩次以上被覆蓋,即爲交集
len[rt] = X[r+1] -X[l];
else if(l == r)//葉子節點長度爲0
len[rt] = 0;
else if(cnt[rt] == 1)//如果覆蓋線段爲1,那麼等於已經覆蓋的左右子樹的長度和
len[rt] = sum[rt<<1] +sum[rt<<1|1];
else //否則等於已經覆蓋的左右子樹長度和。
len[rt] = len[rt<<1] + len[rt<<1|1];
}
int Bin(double key,int n){
return lower_bound(X,X+n,key)-X;
}
void Update(int L,int R,int c,int l,int r,int rt){
if(L<=l && r<=R){
cnt[rt]+=c;
Pushup(l,r,rt);
Pushupagain(l,r,rt);
return ;
}
int m=mid;
if(m>=L)
Update(L,R,c,lson);
if(m<R)
Update(L,R,c,rson);
Pushup(l,r,rt);
Pushupagain(l,r,rt);
}
int main(){
int t,i,j,T;
scanf("%d",&T);
while(T--){
scanf("%d",&t);
double a[4];
int n=0;
for(i=0;i<t;i++){
for(j=0;j<4;j++)
scanf("%lf",&a[j]);
seg[n]=Seg(a[0],a[2],a[1],1);
X[n++]=a[0];
seg[n]=Seg(a[0],a[2],a[3],-1);
X[n++]=a[2];
}
sort(seg,seg+n);
sort(X,X+n);
int k=1;
for(i=1;i<n;i++){ //去重離散化
if(X[i-1]!=X[i])
X[k++]=X[i];
}
memset(cnt,0,sizeof(cnt));
memset(sum,0,sizeof(sum));
memset(len,0,sizeof(len));
double area=0,sre=0;
for(i=0;i<n-1;i++){
int l=Bin(seg[i].l,k);
int r=Bin(seg[i].r,k)-1; //左閉右開區間,取實區時往後移一個
if(l<=r)
Update(l,r,seg[i].c,0,k-1,1);
area+=len[1]*(seg[i+1].h-seg[i].h);
//sre+=sum[1]*(seg[i+1].h-seg[i].h);
}
// printf("Test case #%d\nTotal explored area: %.2lf\n\n",++cas,area);
printf("%.2lf\n",area);
//area 爲面積交,sre爲面積並
}
return 0;
}
hdu 1542 ,1255 線段樹面積並與面積交
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.