POJ 1177-Picture线段树+离散化+扫描线求矩形周长并
周长并和面积并的代码基本上差不多,只不过多了两个rb,lb判定端点是否被覆盖的判断,维护的过程也增加了一点难度,但是整体上是差不多的。
View Code
#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #include <algorithm> #define N 5005 #define L(x) x<<1 #define R(x) x<<1|1 using namespace std; struct node { int l,r,num,len,cov; int lf,rf; bool rb,lb; }; node tree[N<<2]; struct seg { int x,y1,y2,flag; }; seg line[N<<1]; int y[N<<1],cnt; int cmp1(const void *a,const void *b) { return *(int *)a-*(int *)b;; } int cmp2(const void *a,const void *b) { seg *c=(seg *)a; seg *d=(seg *)b; return c->x-d->x; } void add(int x1,int x2,int y1,int y2) { line[cnt].x=x1,line[cnt].y1=y1,line[cnt].y2=y2,line[cnt].flag=1; cnt++; line[cnt].x=x2,line[cnt].y1=y1,line[cnt].y2=y2,line[cnt].flag=-1; cnt++; } void build(int l,int r,int i) { tree[i].l=l; tree[i].r=r; tree[i].num=tree[i].len=0; tree[i].rb=tree[i].lb=false; tree[i].cov=0; tree[i].lf=y[l]; tree[i].rf=y[r]; if(r==l+1) return; int mid=(l+r)>>1; build(l,mid,L(i)); build(mid,r,R(i)); } void length(int i) { if(tree[i].cov>0) { tree[i].len=tree[i].rf-tree[i].lf; tree[i].num=1; tree[i].rb=tree[i].lb=true; return; } else if(tree[i].l==tree[i].r-1) tree[i].num=tree[i].lb=tree[i].rb=tree[i].len=0; else { tree[i].rb=tree[R(i)].rb; tree[i].lb=tree[L(i)].lb; tree[i].len=tree[L(i)].len+tree[R(i)].len; tree[i].num=tree[L(i)].num+tree[R(i)].num-tree[L(i)].rb*tree[R(i)].lb; } } void update(seg l,int i) { if(tree[i].lf==l.y1&&tree[i].rf==l.y2) { tree[i].cov+=l.flag; length(i); return; } if(l.y2<=tree[L(i)].rf) update(l,L(i)); else if(l.y1>=tree[R(i)].lf) update(l,R(i)); else { seg temp; temp=l; temp.y2=tree[L(i)].rf; update(temp,L(i)); temp=l; temp.y1=tree[R(i)].lf; update(temp,R(i)); } length(i); } int main() { int n,i,j,x1,x2,y1,y2,m; while(~scanf("%d",&n)) { cnt=0; m=0; for(i=0;i<n;i++) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); y[m++]=y1; y[m++]=y2; add(x1,x2,y1,y2); } qsort(y,m,sizeof(int),cmp1); qsort(line,cnt,sizeof(seg),cmp2); int t=m; t=unique(y,y+m)-y; build(0,t-1,1); int lines,last,ans; lines=last=ans=0; line[cnt]=line[cnt-1]; for(i=0;i<cnt;i++) { update(line[i],1); if(i) ans+=2*lines*(line[i].x-line[i-1].x); ans+=abs(tree[1].len-last); last=tree[1].len; lines=tree[1].num; } printf("%d\n",ans); } return 0; }