杭电 1828 Picture(线段树+扫描线+周长)

题意:给出一系列矩形的左下和右上点,计算所有矩形堆叠后的周长。

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;
}

猜你喜欢

转载自blog.csdn.net/jack_jxnu/article/details/81389230
今日推荐