hdu 1542 ,1255 線段樹面積並與面積交

/*
在這裏將一個一個的矩形分隔成兩條平行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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章