矩形面积并-扫描线 线段树 离散化 模板-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
",++icase);
118         printf("Total explored area: %.2f

",ans);
119 }
120 
121 int main()
122 {
123     while(scanf("%d",&n)!=EOF&&n){
124         init();
125         solve();
126     }
127     return 0;
128 }
原文地址:https://www.cnblogs.com/GeniusYang/p/5762577.html