zoj 3273 || hdu 3265 Posters

80 篇文章 0 订阅

09宁波区域赛的题。。。09宁波也。。。GB他们在这个区域赛拿铜的那个比赛。。。


矩形面积并,小变形。这个矩形中间有一块是镂空的。所以把每个矩形分成四个小矩形即可。开始以为扫描到镂空的时候就记录减1,扫出的时候就加1,死活不对,我还是切成4个矩形做吧 = =。。

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
#include <climits>
#define MID(x,y) ((x+y)>>1)
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define BUG printf("here!!!\n")

using namespace std;

const int MAX = 200010;
struct Tnode{int l,r,length,cover;};
Tnode node[MAX];
int y[MAX*2];
struct Sline{int x,y1,y2,flag;};
Sline l[MAX*2];
void lineadd(int x1,int x2,int y1,int y2,int &cnt)
{
	l[cnt].x = x1;
	l[cnt].y1 = y1; l[cnt].y2 = y2;
	l[cnt++].flag = 1;
	l[cnt].x = x2;
	l[cnt].y1 = y1; l[cnt].y2 = y2;
	l[cnt++].flag = -1;
}
bool cmp(Sline a,Sline b)
{
	return a.x < b.x;
}
void init()
{
	memset(node,0,sizeof(node));
}
void Build(int t,int l,int r)
{
	node[t].l = l; node[t].r = r;
	node[t].length = 0;
	if( l == r - 1 ) return ;
	int mid = MID(l,r);
	Build(R(t),mid,r);
	Build(L(t),l,mid);
}
void len(int t)
{
	if( node[t].cover > 0 )
		node[t].length = y[node[t].r] - y[node[t].l];
	else
		if( node[t].l == node[t].r - 1 )
			node[t].length = 0;
		else
			node[t].length = node[R(t)].length + node[L(t)].length;
}
void Updata(int t,Sline p)
{
	if( y[node[t].l] >= p.y1 && y[node[t].r] <= p.y2 )
	{
		node[t].cover += p.flag;
		len(t);
		return ;
	}
	if( node[t].l == node[t].r - 1 ) return ;
	int mid = MID(node[t].l,node[t].r);
	if( p.y1 <= y[mid] )
		Updata(L(t),p);
	if( p.y2 > y[mid])
		Updata(R(t),p);
	len(t);
}
void solve(int n,int cnt)
{
	init();
	Build(1,0,cnt-1);
	Updata(1,l[0]);
	__int64 sum = 0;
	for(int i=1; i<n; i++)
	{
		sum += (l[i].x - l[i-1].x)*1ll*node[1].length;
		Updata(1,l[i]);
	}
	printf("%I64d\n",sum);
}
int main()
{
	int n,x1,x2,x3,x4,y1,y2,y3,y4;
	
	while( ~scanf("%d",&n) && n )
	{
		int cnt = 0,cy = 0;
		for(int i=0; i<n; i++)
		{
			scanf("%d%d%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
			lineadd(x1,x2,y4,y2,cnt);
			lineadd(x1,x3,y1,y4,cnt);
			lineadd(x3,x4,y1,y3,cnt);
			lineadd(x4,x2,y1,y2,cnt);	
			
			y[cy++] = y1; y[cy++] = y2; y[cy++] = y3; y[cy++] = y4;
		}
		int t = cnt;
		sort(l,l+cnt,cmp);
		sort(y,y+cy);
		cy = unique(y,y+cy) - y;
		solve(t,cy);
	}
return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值