題目鏈接: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;
}