题意:给出一系列矩形的左下和右上点,计算所有矩形堆叠后的周长。
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
思路:与矩形堆叠求面积有相似之处。
https://blog.csdn.net/jack_jxnu/article/details/81348006
但又不完全相同,具体看代码内注释。
#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
struct Sline
{
int x,y1,y2,flag;
Sline(){}
Sline (int xx,int a,int b,int f):x(xx),y1(a),y2(b),flag(f){}
bool operator< (const Sline &s) const //重载函数
{
if(x==s.x) return flag>s.flag;//如果两条线重叠,先扫描入线,不然会多算重叠部分
return x<s.x;
}
}line[10005];
struct node
{
int cnt,num,len,lh,rh;
//cnt标记区间被覆盖的次数
//num记录区间内有多少段线
//len记录区间有效长度
//lh
//rh
}node[40020];
int y[10005];//离散化
void pushup(int p,int s,int e)
{
if(node[p].cnt)
{
node[p].len=y[e]-y[s-1];
node[p].num=node[p].lh=node[p].rh=1;
}
else if(s==e)
{
node[p].len=node[p].num=node[p].lh=node[p].rh=0;
}
else //区间合并
{
node[p].len=node[p*2].len+node[p*2+1].len;
node[p].num=node[p*2].num+node[p*2+1].num;
node[p].lh=node[p*2].lh;
node[p].rh=node[p*2+1].rh;
if(node[p*2].rh&&node[p*2+1].lh) node[p].num--;
}
}
void update(int p,int s,int e,int l,int r,int v)
{
if(s>=l&&e<=r)
{
node[p].cnt+=v;
pushup(p,s,e);
return;
}
int m=(s+e)/2;
if(l<=m) update(p*2,s,m,l,r,v);
if(r>m) update(p*2+1,m+1,e,l,r,v);
pushup(p,s,e);
}
int main()
{
int n,x1,x2,y1,y2;
while(~scanf("%d",&n))
{
int m=0;
for(int i=0;i<n;i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
y[m]=y1;
y[m+1]=y2;
line[m++]=Sline(x1,y1,y2,1);
line[m++]=Sline(x2,y1,y2,-1);
}
sort(line,line+m);
sort(y,y+m);
int ans=0,last=0,l,r;
for(int i=0;i<m;i++)
{
l=lower_bound(y,y+m,line[i].y1)-y+1;//记录竖线的下端点
r=lower_bound(y,y+m,line[i].y2)-y;//记录竖线的上端点
update(1,1,m,l,r,line[i].flag);
if(i<m-1) ans+= 2*node[1].num*(line[i+1].x-line[i].x);//横边
ans+=abs(node[1].len-last); //竖边
last=node[1].len;
}
printf("%d\n",ans);
}
return 0;
}