扫描线+线段树=矩形周长并
和求面积并差不多,线段树节点维护覆盖长度,线段分段数,是否覆盖,左右端点是否覆盖(判断线段分段数用 right.num+left.num-left.rb*right.lb)。一次扫描直接求出周长。。。(当然也可以求一遍x边长,再求一遍y边长。。。。这样简单的多)
线段排序时要注意Y相同时让左边的边在前,这样就解决重边问题了
Time Limit: 2000MS | Memory Limit: 10000K | |
Total Submissions: 9838 | Accepted: 5205 |
Description
Input
Output
Sample Input
7 -15 0 5 10 -5 8 20 25 15 -4 24 14 0 -6 16 4 2 15 10 22 30 10 36 20 34 0 40 16
Sample Output
228
Source
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define Left(rt) rt<<1 #define Right(rt) rt<<1|1 const int maxn=5500; struct Node { int l,r,len,num,cover,rb,lb; }node[maxn<<2]; struct Line { int yl,yr,x,s; bool operator < (const Line &M) const { if(x!=M.x) return x<M.x; else return s>M.s; } }line[maxn<<1]; int Y[maxn<<1]; int find(int x,int k) { int low=1,high=k,mid; while(low<=high) { mid=(low+high)/2; if(Y[mid]==x) return mid; else if(Y[mid]>x) high=mid-1; else low=mid+1; } } void push_up(int l,int r,int rt) { if(node[rt].cover) { node[rt].num=node[rt].rb=node[rt].lb=1; node[rt].len=Y[r+1]-Y[l]; return ; } if(r==l) { node[rt].len=node[rt].num=node[rt].rb=node[rt].lb=0; return ; } node[rt].len=node[Left(rt)].len+node[Right(rt)].len; node[rt].num=node[Left(rt)].num+node[Right(rt)].num-node[Left(rt)].rb*node[Right(rt)].lb; node[rt].rb=node[Right(rt)].rb;node[rt].lb=node[Left(rt)].lb; } void update(int l,int r,int rt,int L,int R,int c) { if(L<=l&&r<=R) { node[rt].cover+=c; push_up(l,r,rt); return ; } int m=(l+r)>>1; if(L<=m) update(lson,L,R,c); if(R>m) update(rson,L,R,c); push_up(l,r,rt); } void build(int l,int r,int rt) { node[rt].l=l; node[rt].r=r; if(l==r) return ; int m=(l+r)/2; build(lson);build(rson); } int main() { int n; while(scanf("%d",&n)!=EOF&&n) { memset(node,0,sizeof(node)); memset(Y,0,sizeof(Y)); int x1,x2,y1,y2,cnt=0,k; for(int i=0;i<n;i++) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); line[++cnt]=(Line){y1,y2,x1,1}; Y[cnt]=y1; line[++cnt]=(Line){y1,y2,x2,-1}; Y[cnt]=y2; } sort(line+1,line+1+cnt); sort(Y+1,Y+1+cnt); k=unique(Y+1,Y+1+cnt)-Y-1; int ans=0,last=0; for(int i=1;i<=cnt;i++) { int l=find(line[i].yl,k); int r=find(line[i].yr,k)-1; update(1,k-1,1,l,r,line[i].s); if(i!=cnt) ans+=node[1].num*2*(line[i+1].x-line[i].x);//x ans+=abs(node[1].len-last);//y last=node[1].len; } printf("%d\n",ans); } return 0; }
原文:http://blog.csdn.net/u012797220/article/details/18817449