pku1177 Picture

思路:
1,对y坐标离散化,设有ycnt个不同的y值,在[0,ycnt]上建立线段树
2,建立竖边结构(每个矩形有两条竖边,n个矩形有2*n条竖边):
  struct Edge{
   int yu;//竖边上端点y坐标
   int yd;//下端点y坐标
   int x;//x坐标
   int tag;//竖边类型
  }
   把所有竖边分为IN和OUT两类,再对x排序,扫描线遇到IN则对线段树插入[yd,yu],遇到OUT则删除[yd,yu],注意只有曾经插入过的区间才能够进行删除
3,说说线段树的结点:
  struct Node{
   int l,r;//区间
   int cnt;//计数器
   int nseg,nlen;//扫描线被矩形覆盖的部分的段数和长度
   bool lc,rc;//若该区间左右端点是否被覆盖的标记
  }
 设xans和yans分别为竖轮廓和横轮廓的长度,root'和root分别记录了扫描线在位置x1和x2时区间[0,ycnt]的信息,若扫描线从x1扫描至x2,则xans和yans有如下变化:
  xans+=root'.nseg*2*(x2-x1);
  yans+=abs(root.nlen-root'.nlen);
  
 另外,在插入和删除操作中要注意对线段树结点信息的维护

 

 

#include <iostream>
#include 
<algorithm>
using namespace std;

#define IN 1
#define OUT 0
#define MAXN 10001
#define clr(x) memset(x,0,sizeof(x));

int n,ycnt,yinterval[2*MAXN],yans,xans;
//yinterval[i]=y表示纵坐标经过排序后第i个不同的纵坐标为y
int sy[2*MAXN];
//sy[y]=i表示纵坐标经过排序后y是第i小的纵坐标,与yinterval[i]=y互为反函数

struct Edge{
    
int yu,yd,x,tag;
}e[
2*MAXN];

struct Node{
    
int l,r;
    
int cnt;
    
int nseg,nlen;
    
bool lc,rc;
}nod[
3*MAXN];

class CP{
public:
    
int operator()(Edge &arg1,Edge &arg2){
        
return arg1.x<arg2.x;
    }
};



void buildtree(int v,int l,int r){
    nod[v].l
=l;
    nod[v].r
=r;
    nod[v].lc
=nod[v].rc=false;
    nod[v].nlen
=nod[v].nseg=0;
    nod[v].cnt
=0;
    
if(r-l==1)
        
return;
    buildtree(
2*v,l,(l+r)/2);
    buildtree(
2*v+1,(l+r)/2,r);
}



void init(){
    
int i,xl,xr,yu,yd;
    ycnt
=0;
    clr(sy);
    
for(i=0;i<n;i++){
        scanf(
"%d%d%d%d",&xl,&yd,&xr,&yu);
        e[
2*i].yu=yu;
        e[
2*i].yd=yd;
        e[
2*i].x=xl;
        e[
2*i].tag=IN;
        e[
2*i+1].yu=yu;
        e[
2*i+1].yd=yd;
        e[
2*i+1].x=xr;
        e[
2*i+1].tag=OUT;
        
if(!sy[yd]){
            yinterval[ycnt
++]=yd;
            sy[yd]
=1;
        }
        
if(!sy[yu]){
            yinterval[ycnt
++]=yu;
            sy[yu]
=1;
        }
    }
    sort(yinterval,yinterval
+ycnt);
    
for(i=0;i<ycnt;i++)
        sy[yinterval[i]]
=i;
    sort(e,e
+2*n,CP());
    buildtree(
1,0,ycnt-1);

}

void insert(int v,int l,int r){
    
if(l<=nod[v].l && nod[v].r<=r){
        nod[v].nlen
=yinterval[nod[v].r]-yinterval[nod[v].l];
        nod[v].cnt
++;
        nod[v].nseg
=1;
        nod[v].lc
=true;
        nod[v].rc
=true;
        
return;
    }
    
if(l<nod[2*v].r)
        insert(
2*v,l,r);
    
if(r>nod[2*v+1].l)
        insert(
2*v+1,l,r);
    
if(nod[v].cnt==0){
        nod[v].lc
=nod[2*v].lc;
        nod[v].rc
=nod[2*v+1].rc;
        nod[v].nlen
=nod[2*v].nlen+nod[2*v+1].nlen;
        nod[v].nseg
=nod[2*v].nseg+nod[2*v+1].nseg;
        
if(nod[2*v].rc && nod[2*v+1].lc)
            nod[v].nseg
--;
    }
}

void del(int v,int l,int r){
    
if(l<=nod[v].l && nod[v].r<=r){
        nod[v].cnt
--;
        
if(nod[v].cnt==0){
            
if(nod[v].r-nod[v].l==1){
                nod[v].lc
=nod[v].rc=false;
                nod[v].nlen
=nod[v].nseg=0;
            }
            
else{
                nod[v].lc
=nod[2*v].lc;
                nod[v].rc
=nod[2*v+1].rc;
                nod[v].nlen
=nod[2*v].nlen+nod[2*v+1].nlen;
                nod[v].nseg
=nod[2*v].nseg+nod[2*v+1].nseg;
                
if(nod[2*v].rc && nod[2*v+1].lc)
                    nod[v].nseg
--;
            }
        }
        
return;
    }

    
if(l<nod[2*v].r)
        del(
2*v,l,r);
    
if(r>nod[2*v+1].l)
        del(
2*v+1,l,r);
    
if(nod[v].cnt==0){
        nod[v].lc
=nod[2*v].lc;
        nod[v].rc
=nod[2*v+1].rc;
        nod[v].nlen
=nod[2*v].nlen+nod[2*v+1].nlen;
        nod[v].nseg
=nod[2*v].nseg+nod[2*v+1].nseg;
        
if(nod[2*v].rc && nod[2*v+1].lc)
            nod[v].nseg
--;
    }
}
        

void cal(){
    yans
=0;
    xans
=0;
    
int i;
    insert(
1,sy[e[0].yd],sy[e[0].yu]);
    yans
=nod[1].nlen;
    memcpy(nod,nod
+1,sizeof(nod[0]));

    
for(i=1;i<2*n;i++){
        
if(e[i].tag==IN)
            insert(
1,sy[e[i].yd],sy[e[i].yu]);
        
else
            del(
1,sy[e[i].yd],sy[e[i].yu]);
        yans
+=abs(nod[1].nlen-nod[0].nlen);
        xans
+=2*nod[0].nseg*(e[i].x-e[i-1].x);
        memcpy(nod,nod
+1,sizeof(nod[0]));
    }
}
            

int main(){
    
while(scanf("%d",&n)!=EOF){
        init();
        cal();
        printf(
"%d\n",yans+xans);
    }
    
return 0;
}
posted @ 2008-10-17 16:52  Beetlebum  阅读(854)  评论(0编辑  收藏  举报