PKU 1389 Area of Simple Polygons

题目:http://poj.org/problem?id=1389

题意:给出n个矩形的左下角和右上角,求出所有矩形面积的并

思路:线段树+离散化+扫描线

#include <stdio.h>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=2000;
struct SegMentTree
{
	int l, r, cover, len, sum;
}st[maxn<<2];
struct Line
{
	int y_top, y_btm, x;
	int in;
	bool operator<(Line l) const 
	{
		return x<l.x;
	}
}l[maxn+10];
int y[maxn+10], ans, cnt;
void BuildTree(int v, int left, int right)
{
	st[v].l=left, st[v].r=right, st[v].cover=0, st[v].len=y[right]-y[left];
	if (right-left==1)
	{
		st[v].sum=0;
		return;
	}
	int lc=v<<1;
	int rc=lc+1;
	int mid=(left+right)>>1;
	BuildTree(lc, left, mid);
	BuildTree(rc, mid, right);
	st[v].sum=st[lc].sum+st[rc].sum;
}
void Update(int x)
{

	if (st[x].cover>0) st[x].sum=st[x].len;
	else if (st[x].r-st[x].l>1) st[x].sum=st[x*2].sum+st[x*2+1].sum;
	else st[x].sum=0;
}
void Insert(int v, int left, int right)
{
	if (st[v].l==left&&st[v].r==right) st[v].cover++;
	else
	{
		int lc=v<<1;
		int rc=lc+1;
		int mid=(st[v].l+st[v].r)>>1;
		if (right<=mid) Insert(lc, left, right);
		else if (left>=mid) Insert(rc, left, right);
		else 
		{
			Insert(lc, left, mid);
			Insert(rc, mid, right);
		} 
	}
	Update(v);
}
void Delete(int v, int left, int right)
{
	if (st[v].l==left&&st[v].r==right) st[v].cover--;
	else
	{
		int lc=v<<1;
		int rc=lc+1;
		int mid=(st[v].l+st[v].r)>>1;
		if (right<=mid) Delete(lc, left, right);	
		else if (left>=mid) Delete(rc, left, right);
		else
		{
			Delete(lc, left, mid);
			Delete(rc, mid, right);
		}
	}
	Update(v);
}
int GetIndex(int x)
{
	return lower_bound(y, y+cnt, x)-y;
}
int main()
{
	//freopen("in.txt", "r", stdin);
	int x1, y1, x2, y2;
	while (scanf("%d %d %d %d", &x1, &y1, &x2, &y2)==4)
	{
		int i=0;
		if (x1==-1&&y1==-1&&x2==-1&&y2==-1) break;
		do
		{
			l[i*2].y_top=l[i*2+1].y_top=y1;
	 		l[i*2].y_btm=l[i*2+1].y_btm=y2;
			l[i*2].x=x1, l[i*2+1].x=x2;
			l[i*2].in=1, l[i*2+1].in=0;
			y[i*2]=y1, y[i*2+1]=y2;
			i++;
		}while (scanf("%d %d %d %d", &x1, &y1, &x2, &y2)&&(x1!=-1&&y1!=-1&&x2!=-1&&y2!=-1));
		sort(y, y+2*i);
		sort(l, l+2*i);
		cnt=0;
		for (int j=1; j<2*i; j++)
		{	
			if (y[j]!=y[j-1]) y[cnt++]=y[j-1];
		}	
		y[cnt++]=y[2*i-1];
		BuildTree(1, 0, cnt-1);
		ans=0;
		for (int j=0; j<2*i-1; j++)
		{
			if (l[j].in) Insert(1, GetIndex(l[j].y_top), GetIndex(l[j].y_btm));
			else Delete(1, GetIndex(l[j].y_top), GetIndex(l[j].y_btm));
			ans+=(l[j+1].x-l[j].x)*st[1].sum;
		}
		printf("%d\n", ans);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值