hdu 1542 線段樹之掃描線之面積並
阿新 • • 發佈:2019-02-11
題意:給你n個矩形,求它們的面積,重複的不重複計算
思路:用線段樹的掃描線完成,將X座標離散化後,從下到上掃描矩形,進行各種處理,看程式碼註釋把
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int maxn=1e3+10; #define mm(a) memset(a,0,sizeof(a)) int num1[maxn*4]; double num[maxn*4],X[maxn*4]; struct edge{ double l,r,h; int s;//s為1是下邊,s為-1是上邊 edge(){}; edge(double a,double b,double c,int d) : l(a),r(b),h(c),s(d){} bool operator<(const edge &n)const{ return h<n.h; } }ss[maxn]; void pushup(int le,int ri,int node){ if(num1[node]) num[node]=X[ri+1]-X[le];//在更新的時候,可能兩個矩陣有重疊,這樣就不能像以前那麼更新,而是將le和ri傳入 else if(le==ri) num[node]=0; //然後將X[ri+1]-X[le]的值進行更新,避免了重複的長度 else num[node]=num[node<<1]+num[node<<1|1]; } void update(int l,int r,int add,int le,int ri,int node){ if(l<=le&&ri<=r){ num1[node]+=add;//與懶惰標記類似 pushup(le,ri,node); return ; } int t=(le+ri)>>1; if(l<=t) update(l,r,add,le,t,node<<1); if(r>t) update(l,r,add,t+1,ri,node<<1|1); pushup(le,ri,node); } int main(){ int n,t=1; while(scanf("%d",&n)!=-1){ if(n==0) break; double a,b,c,d; int k=0; for(int i=0;i<n;i++){ scanf("%lf%lf%lf%lf",&a,&b,&c,&d); X[k]=a; ss[k++]=edge(a,c,b,1); X[k]=c; ss[k++]=edge(a,c,d,-1); } sort(X,X+k); sort(ss,ss+k); int k1=1; for(int i=1;i<k;i++){//對X進行離散化 if(X[i]!=X[i-1]) X[k1++]=X[i]; } mm(num);mm(num1); double ans=0; for(int i=0;i<k-1;i++){ int l=lower_bound(X,X+k1,ss[i].l)-X; int r=lower_bound(X,X+k1,ss[i].r)-X-1; update(l,r,ss[i].s,0,k1-1,1); ans+=num[1]*(ss[i+1].h-ss[i].h);//num[1]為當前橫座標的總長度 } printf("Test case #%d\nTotal explored area: %.2f\n\n",t++,ans); } return 0; }