矩形面积并-扫描线 线段树 离散化 模板-poj1151 hdu1542
今天刚看到这个模板我是懵逼的,这个线段树既没有建树,也没有查询,只有一个update,而且区间成段更新也没有lazy标记....研究了一下午,我突然我发现我以前根本不懂扫描线,之所以没有lazy标记,是因为扫描线每次只查询1-n里的所有有值的区间长度,因为只要1-n,而不会查找到某些小区间,所以也就不用lazy,而且也无需查询,每次插入完只需要 知道sum[1]是多少即可。所以一个update函数即可。注意的是,线段树的叶子节点不是x轴或者y轴上的点,而是一个个区间,由矩形的长或者宽间距所构成的区间。比如 你现在要更新的这条边的两个端点在x轴上是 x=1,和x=6,更新的l=1,r=5,因为1->6 中间有5个区间 偷别人博客的一张图来看一下就是这样的效果:
所以线段树维护的是 这些小区间
然后剩下的细节就很好懂了
1 #include<cstdio> 2 3 #include<string.h> 4 5 #include<algorithm> 6 7 #define inf 0x3f3f3f3f 8 9 const int maxn=1000; 10 11 using namespace std; 12 13 #define lson (id<<1) 14 15 #define rson ((id<<1)|1) 16 17 #define mid ((l+r)>>1) 18 19 double a[maxn+10]; 20 21 double sum[maxn+10]; 22 23 int flag[maxn+10]; 24 25 int n,l,r,k,cnt,icase; 26 27 double ans; 28 29 double X1,Y1,X2,Y2; 30 31 struct node{ 32 double lx,rx,y; 33 int f; 34 node(){}; 35 node(double lx_,double rx_,double y_,int f_){ 36 lx=lx_,rx=rx_,y=y_,f=f_; 37 } 38 }line[maxn+10]; 39 40 int cmp(node a,node b){ 41 return a.y<b.y; 42 } 43 44 int bin_search(double val){ 45 int lb=1,ub=k; 46 int Mid=(lb+ub)>>1; 47 while(ub-lb>1){ 48 Mid=(ub+lb)>>1; 49 if(a[Mid]==val) return Mid; 50 else if(a[Mid]>val) ub=Mid; 51 else if(a[Mid]<val) lb=Mid; 52 } 53 if(a[Mid]==val) return Mid; 54 if(a[ub]==val) return ub; 55 if(a[lb]==val) return lb; 56 } 57 58 void push_up(int id,int l,int r){ 59 if(flag[id]) sum[id]=a[r+1]-a[l]; 60 else if(l==r) sum[id]=0; 61 else sum[id]=sum[lson]+sum[rson]; 62 } 63 64 void update(int id,int l,int r,int ql,int qr,int val){ 65 if(ql<=l&&r<=qr){ 66 flag[id]+=val; 67 push_up(id,l,r); 68 return ; 69 } 70 if(ql<=mid){ 71 update(lson,l,mid,ql,qr,val); 72 } 73 if(qr>=mid+1){ 74 update(rson,mid+1,r,ql,qr,val); 75 } 76 if(qr<=mid){ 77 update(lson,l,mid,ql,qr,val); 78 } else if(ql>=mid+1){ 79 update(rson,mid+1,r,ql,qr,val); 80 } else { 81 update(lson,l,mid,ql,mid,val); 82 update(rson,mid+1,r,mid+1,qr,val); 83 } 84 push_up(id,l,r); 85 } 86 87 void init(){ 88 k=0; 89 cnt=0; 90 ans=0; 91 memset(flag,0,sizeof(flag)); 92 memset(sum,0,sizeof(sum)); 93 } 94 95 void solve(){ 96 for(int i=1;i<=n;i++){ 97 scanf("%lf%lf%lf%lf",&X1,&Y1,&X2,&Y2); 98 line[++cnt]=node(X1,X2,Y1,1); 99 a[cnt]=X1; 100 line[++cnt]=node(X1,X2,Y2,-1); 101 a[cnt]=X2; 102 } 103 sort(a+1,a+1+cnt); 104 sort(line+1,line+1+cnt,cmp); 105 k=1; 106 for(int i=2;i<=cnt;i++){ 107 if(a[i]!=a[i+1]){ 108 a[++k]=a[i]; 109 } 110 } 111 for(int i=1;i<cnt;i++){ 112 l=bin_search(line[i].lx); 113 r=bin_search(line[i].rx)-1; 114 update(1,1,k,l,r,line[i].f); 115 ans+=sum[1]*(line[i+1].y-line[i].y); 116 } 117 printf("Test case #%d\n",++icase); 118 printf("Total explored area: %.2f\n\n",ans); 119 } 120 121 int main() 122 { 123 while(scanf("%d",&n)!=EOF&&n){ 124 init(); 125 solve(); 126 } 127 return 0; 128 }