Hdu 1255 覆蓋的面積 線段樹+矩形面積並
阿新 • • 發佈:2019-02-13
繼續面積並學習中。。。(線段樹解決)
題意:給定平面上若干矩形,求出被這些矩形覆蓋過至少兩次的區域的面積
思路:其實跟求矩形面積並的思想是一樣的,只不過在update裡做了一點修改,矩形面積並只需要求至少覆蓋一次的面積,而這題是至少覆蓋兩次的面積,稍微做點修改就可以了
一樣的,要求面積,就要求出至少覆蓋兩次的有效長度乘以高度差即可,求有效長度:
1.cnt>1 : 說明該區間被覆蓋兩次或以上,那麼長度就可以直接計算,就是該區間的長度
剩下的情況就是cnt=1或cnt=0
2.先看葉子節點,因為是葉子沒有孩子了,所以被覆蓋兩次貨以上的長度就是0(無論cnt=1或cnt=0都是0,因為是葉子。。。)
3.不是葉子節點 ,且cnt=1.注意這裡,cnt=1確切的意義是什麼,應該是,可以確定,這個區間被完全覆蓋了1次,而有沒有被完全覆蓋兩次或以上則不知道無法確定,那麼怎麼怎麼辦了,只要加上sum1[左孩子]+sum1[右孩子] 即看看左右孩子區間被覆蓋了一次或以上的長度,那麼疊加在雙親上就是雙親被覆蓋兩次或以上的長度
4.不是葉子節點,且cnt=0,確切的意義應該是不完全不知道被覆蓋的情況(不知道有沒有被覆蓋,被覆蓋了幾次,長度是多少都不知道),這種情況,只能由其左右孩子的資訊所得
sum2[左孩子]+sum2[右孩子] , 即直接將左右孩子給覆蓋了兩次或以上的長度加起來,這樣才能做到不重不漏
這裡:我用sum1代表至少被覆蓋一次的有效長度,sum2代表至少覆蓋兩次的有效長度
程式碼:
#include <iostream> #include <stdio.h> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <map> #include <queue> #define lson l,mid,num<<1 #define rson mid+1,r,num<<1|1 using namespace std; const int M=2010; double sum1[M<<2],sum2[M<<2]; int cnt[M<<2]; double x[M]; struct node { double l,r,h; int flag; node() {} node(double x1,double x2,double y,int s) :l(x1),r(x2),h(y),flag(s) {} bool operator <(const node& rsh)const { return h<rsh.h; } } line[M]; int Bin(double key,int n,double x[]) { int l=0,r=n-1; while(l<=r) { int mid=(l+r)>>1; if(x[mid]==key)return mid; else if(x[mid]<key)l=mid+1; else r=mid-1; } return -1; } //void build(int l,int r,int num) //{ // sum1[num]=sum2[num]=cnt[num]=0; // if(l==r) // return; // int mid=(l+r)>>1; // build(lson); // build(rson); //} void PushUp(int num,int l,int r) { if(cnt[num]) sum1[num] = x[r+1]-x[l]; else if(l==r)sum1[num]=0;//判斷葉子結點,只要是葉子結點就都為0 else sum1[num]=sum1[num<<1]+sum1[num<<1|1]; if(cnt[num]>1)sum2[num]=x[r+1]-x[l]; else if(l==r)sum2[num]=0;//判斷葉子結點,只要是葉子結點就都為0 else if(cnt[num]==1) sum2[num]=sum1[num<<1]+sum1[num<<1|1]; else sum2[num]=sum2[num<<1]+sum2[num<<1|1]; } void update(int L,int R,int flag,int l,int r,int num) { if(L<=l && r<=R) { cnt[num]+=flag; PushUp(num,l,r); return; } int mid=(l+r)>>1; if(L<=mid)update(L,R,flag,lson); if(R>mid)update(L,R,flag,rson); PushUp(num,l,r); } int main() { int t,n; scanf("%d",&t); while(t--) { double x1,x2,y2,y1; scanf("%d",&n); int st=0; while(n--) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); x[st]=x1; line[st++]=node(x1,x2,y1,1); x[st]=x2; line[st++]=node(x1,x2,y2,-1); } sort(x,x+st); sort(line,line+st); int k=1; for(int i=1; i<st; i++) { if(x[i]!=x[i-1])x[k++]=x[i]; } //build(0,k-1,1); memset(sum1,0,sizeof(sum1)); memset(sum2,0,sizeof(sum2)); memset(cnt,0,sizeof(cnt)); double ret=0; for(int i=0; i<st-1; i++) { int lx=Bin(line[i].l,k,x); int rx=Bin(line[i].r,k,x)-1; if(lx<=rx)update(lx,rx,line[i].flag,0,k-1,1); ret+=sum2[1]*(line[i+1].h-line[i].h); } printf("%.2lf\n",ret); } return 0; }