扫描线+线段树=矩形周长并
和求面积并差不多,线段树节点维护覆盖长度,线段分段数,是否覆盖,左右端点是否覆盖(判断线段分段数用 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