题目链接:http://poj.org/problem?id=1177
题意:给出多个矩形,求这些矩形所覆盖图形的周长。
可用线段树来做,两种方法:
1、分别对x和y方向离散化后做线段树,求出各方向上的轮廓长;
2、对一个方向上的坐标进行离散化,用另一维进行扫描;
其中,第二个方法要在线段树中维护的值域包括:
1、覆盖的线段长度;
2、不相边的线段数;
3、该节点表示的区间两端点是否被覆盖(用于合并线段);
Code
#include<stdio.h> #include<string.h> #include<stdlib.h> #define M 20008 #define L(x) (x<<1) #define R(x) (x<<1|1) #define Mid(x,y) ((x+y)>>1) typedef struct{ int l,r; int len,c,a; char lc,rc; void init(){ l=r=len=c=a=0; lc=rc=0; } }SegT; typedef struct Line{ int x,y0,y1; char f; Line(){} Line(int _x,int _y0,int _y1,char _f) { set(_x,_y0,_y1,_f); } void set(int _x,int _y0,int _y1,char _f) { x=_x;y0=_y0;y1=_y1;f=_f; } }Line; SegT t[M<<2]; Line ls[M]; int ys[M]; int yn; int n; int ans,len; int Abs(int a) { return a<0?-a:a; } int Cmpy(const void *a,const void *b) { return *(int *)a-*(int *)b; } int Cmpl(const void *a,const void *b) { Line *p=(Line *)a; Line *q=(Line *)b; if(p->x==q->x) return q->f-p->f; return p->x-q->x; } void Create(int i,int lt,int rt) { int mid; t[i].init(); t[i].l=lt;t[i].r=rt; if(lt+1<rt){ mid=Mid(lt,rt); Create(L(i),lt,mid); Create(R(i),mid,rt); } } void Cal(int i) { if(t[i].c>0){ t[i].a=1; t[i].lc=t[i].rc=1; t[i].len=ys[t[i].r]-ys[t[i].l]; } else if(t[i].l+1==t[i].r){ t[i].a=0;t[i].len=0; t[i].lc=t[i].rc=0; } else{ t[i].a=t[L(i)].a+t[R(i)].a-(t[L(i)].rc&t[R(i)].lc); t[i].len=t[L(i)].len+t[R(i)].len; t[i].lc=t[L(i)].lc;t[i].rc=t[R(i)].rc; } } void Updata(int i,Line l) { int mid; if(t[i].l+1==t[i].r){ t[i].c+=l.f; Cal(i); return ; } mid=Mid(t[i].l,t[i].r); if(l.y1<=ys[mid]) Updata(L(i),l); else if(l.y0>=ys[mid]) Updata(R(i),l); else{ Updata(L(i),Line(l.x,l.y0,ys[mid],l.f)); Updata(R(i),Line(l.x,ys[mid],l.y1,l.f)); } Cal(i); } int main() { int i,j; int xo,xl,yo,yl; while(~scanf("%d",&n)){ for(i=0;i<n;i++){ scanf("%d%d%d%d",&xo,&yo,&xl,&yl); ls[L(i)].set(xo,yo,yl,1); ls[R(i)].set(xl,yo,yl,-1); ys[L(i)]=yo;ys[R(i)]=yl; } qsort(ys,L(n),sizeof(ys[0]),Cmpy); qsort(ls,L(n),sizeof(ls[0]),Cmpl); for(i=j=0,n<<=1;i<n;i++){ if(ys[i]==ys[j]) continue; ys[++j]=ys[i]; }yn=++j; Create(1,0,yn); Updata(1,ls[0]); ans=len=0; for(i=1;i<n;i++){ ans+=(ls[i].x-ls[i-1].x)*t[1].a*2; ans+=Abs(len-t[1].len); len=t[1].len; Updata(1,ls[i]); }ans+=len; printf("%d\n",ans); } return 0; }