昨天学完了矩形的并求面积,是看看小HH的博客做的。。大概对扫描线有一个初步的了解,今天果断学习求矩形的并的周长,哎,明显费劲很多,但本菜坚决没有看大牛的代码,果断自己独立完成,而且1A。。。。
预处理不说了,和求矩形并的面积是一样的,只不过要把左右边也要存储在一个数组中,然后排序离散化。。略。重点说以下线段树部分,先说处理横向线段。对每一条线段做查询和更新操作,查询就是求新线段中未覆盖部分,更新则改变该条线段的状态。。。若是底边,先查询,后更新。若是上边,则顺序相反。处理左右边与上下边是一样的,附代码:
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define cl(a) memset(a,0,sizeof(a))
#define N 10010
#define ss(a) scanf("%d",&a)
#define read(a,b,c,d) scanf("%d%d%d%d",&a,&b,&c,&d)
using namespace std;
struct seg
{
int l;
int r;
int h;
int t;
seg(){}
seg(int a,int b,int c,int d):l(a),r(b),h(c),t(d)
{
}
}line[N],vert[N];
int sum[N<<3],col[N<<3],x[N],res,y[N];
bool cmp(seg p,seg q)
{
return p.h<q.h;
}
int bin(int key,int l,int r)
{
if (r-l<=1)
{
if (key==x[l]) return l;
else return r;
}
int m=(l+r)/2;
if (key==x[m]) return m;
else if (key<x[m]) return bin(key,l,m-1);
else return bin(key,m+1,r);
}
void pushup(int l,int r,int rt)
{
if (col[rt]) sum[rt]=0;
else if (l==r) sum[rt]=x[r+1]-x[l];
else sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt)
{
if (l==r)
{
sum[rt]=x[r+1]-x[l];
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(l,r,rt);
}
void update(int L,int R,int c,int l,int r,int rt)
{
if (L<=l&&r<=R)
{
col[rt]+=c;
pushup(l,r,rt);
return;
}
int m=(l+r)>>1;
if (L<=m) update(L,R,c,lson);
if (R>m) update(L,R,c,rson);
pushup(l,r,rt);
}
int query(int L,int R,int l,int r,int rt)
{
if (col[rt]) return 0;
if (L<=l&&r<=R) return sum[rt];
int m=(l+r)>>1,res=0;
if (L<=m) res+=query(L,R,lson);
if (R>m) res+=query(L,R,rson);
return res;
}
void deal(int m,int k)
{
cl(sum);cl(col);
build(1,k,1);
int i,l,r,t0;
for (i=1;i<=m;i++)
{
l=bin(line[i].l,1,k);
r=bin(line[i].r,1,k)-1;
t0=line[i].t;
if (l>r) continue;
if (t0==1)
{
res+=query(l,r,1,k,1);
update(l,r,1,1,k,1);
}
else
{
update(l,r,-1,1,k,1);
res+=query(l,r,1,k,1);
}
}
}
int main()
{
int n,i;
while (ss(n)!=EOF)
{
int a,b,c,d;
int m=0,k=1;
for (i=1;i<=n;i++)
{
read(a,b,c,d);
line[++m]=seg(a,c,b,1);
vert[m]=seg(b,d,a,1);
x[m]=a;
y[m]=b;
line[++m]=seg(a,c,d,-1);
vert[m]=seg(b,d,c,-1);
x[m]=c;
y[m]=d;
}
sort(x+1,x+m+1);
sort(line+1,line+m+1,cmp);
for (i=2;i<=m;i++)
if (x[i]!=x[i-1]) x[++k]=x[i];
res=0;
deal(m,k);
sort(y+1,y+m+1);
sort(vert+1,vert+m+1,cmp);
k=1;
x[1]=y[1];
line[1]=vert[1];
for (i=2;i<=m;i++)
{
if (y[i]!=y[i-1]) x[++k]=y[i];
line[i]=vert[i];
}
deal(m,k);
printf("%d\n",res);
}
return 0;
}