線段樹 + 掃描線 - HDU 1255 - 覆蓋的面積
阿新 • • 發佈:2020-11-15
線段樹 + 掃描線 - HDU 1255 - 覆蓋的面積
對於每個區間結點,建立兩個變數len1
,len2
len1
表示區間內被覆蓋過一次且僅以次的線段長度len2
表示區間內被覆蓋過大於等於兩次的線段長度
因此,對於葉子結點:
if(l+1==r){ if(cover[rt]==1){ tree[rt].len1 = ordy[r]-ordy[l]; tree[rt].len2 = 0; }else if(cover[rt] >= 2){ tree[rt].len1 = 0; tree[rt].len2 = ordy[r] - ordy[l]; }else{ tree[rt].len1 = tree[rt].len2 = 0; } return; }
對於非葉子節點
if(cover[rt] >= 2){ tree[rt].len1 = 0; tree[rt].len2 = ordy[r] - ordy[l]; }else if(cover[rt] == 1){ tree[rt].len2 = tree[rt<<1].len1 + tree[rt<<1|1].len1 + tree[rt<<1].len2 + tree[rt<<1|1].len2; tree[rt].len1 = ordy[r]-ordy[l]-tree[rt].len2; }else{ tree[rt].len1 = tree[rt<<1].len1 + tree[rt<<1|1].len1; tree[rt].len2 = tree[rt<<1].len2 + tree[rt<<1|1].len2; }
完整程式碼
#include <cstdio> #include <cmath> #include <algorithm> using namespace std; #define EPS 1e-9 const int N = 1000+50; bool equals(double a,double b){ return fabs(a-b) < EPS; } struct node{ double len1; // 當前區間僅被覆蓋過一次 double len2; // 當前區間至少被覆蓋過兩次的長度 node(){len1=0;len2=0;} }; struct SL{ double x,upy,downy; int d; SL(){} SL(double a,double b,double c,int d) :x(a),upy(b),downy(c),d(d){} bool operator<(SL&m){ if(!equals(x,m.x)) return x < m.x; else return d > m.d; } }; int my_unique(double arr[],int arrlen){ arr[0]=arr[1]-1; int ptr = 0; for(int i = 1; i <= arrlen; i++){ if(equals(arr[i],arr[i-1])){ continue; }else{ arr[++ptr] = arr[i]; } } return ptr; } int my_lower_bound(double arr[],int len,double val){ // 找到第一個大於等於val的值 ,如果大於等於val,r=mid int l = 1,r = len; while(l < r){ int mid = l+r>>1; if(equals(arr[mid],val) || arr[mid] >= val){ r = mid; }else{ l = mid+1; } } return l; } int cnt; int len; SL SLarr[N<<1]; double ordy[N<<1]; int cover[N<<3]; node tree[N<<3]; void push_up(int l,int r,int rt){ if(l+1==r){ if(cover[rt]==1){ tree[rt].len1 = ordy[r]-ordy[l]; tree[rt].len2 = 0; }else if(cover[rt] >= 2){ tree[rt].len1 = 0; tree[rt].len2 = ordy[r] - ordy[l]; }else{ tree[rt].len1 = tree[rt].len2 = 0; } return; } if(cover[rt] >= 2){ tree[rt].len1 = 0; tree[rt].len2 = ordy[r] - ordy[l]; }else if(cover[rt] == 1){ tree[rt].len2 = tree[rt<<1].len1 + tree[rt<<1|1].len1 + tree[rt<<1].len2 + tree[rt<<1|1].len2; tree[rt].len1 = ordy[r]-ordy[l]-tree[rt].len2; }else{ tree[rt].len1 = tree[rt<<1].len1 + tree[rt<<1|1].len1; tree[rt].len2 = tree[rt<<1].len2 + tree[rt<<1|1].len2; } } void update(int l,int r,int rt,int ul,int ur,int d){ if(ul <= l && ur >= r){ cover[rt] += d; push_up(l,r,rt); }else{ if(l+1==r)return; int mid = l+r>>1; if(ul <= mid){ update(l,mid,rt<<1,ul,ur,d); } if(ur > mid){ update(mid,r,rt<<1|1,ul,ur,d); } push_up(l,r,rt); } } void clear(int l,int r,int rt){ tree[rt].len1 = tree[rt].len2 = 0; cover[rt] = 0; if(l+1==r)return; int mid = l+r>>1; clear(l,mid,rt<<1); clear(mid,r,rt<<1|1); } int main(){ int T; scanf("%d",&T); for(int t = 1; t <= T; t++){ int n; double xa,ya,xb,yb; scanf("%d",&n); cnt=len=0; for(int i = 1;i <= n; i++){ scanf("%lf%lf%lf%lf",&xa,&ya,&xb,&yb); SLarr[++cnt] = SL(xa,yb,ya,1); ordy[cnt] = ya; SLarr[++cnt] = SL(xb,yb,ya,-1); ordy[cnt] = yb; } sort(ordy+1,ordy+1+cnt); sort(SLarr+1,SLarr+1+cnt); len = my_unique(ordy,cnt); clear(1,len,1); double ans = 0.00; for(int i = 1; i <= cnt; i++){ ans += tree[1].len2 * (SLarr[i].x-SLarr[i-1].x); int ul = my_lower_bound(ordy,len,SLarr[i].downy); int ur = my_lower_bound(ordy,len,SLarr[i].upy); update(1,len,1,ul,ur,SLarr[i].d); } printf("%.2f\n",ans); } system("pause"); return 0; }