hdu1828 Picture(扫描线+矩形周长并+线段树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1828

题意:给出一些矩形,求并后的周长。

哈希后,扫描即可。第一道扫描线的题目,尽管是裸题,还是可开心~~

参考代码:

#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
using namespace std;

#define clr(arr,val) memset(arr,val,sizeof(arr))
const int M = 5005;

enum In{lt,rt};
int n;
int hash_y[M*4],num_y[M*2],decod[M*2],MaxY;
struct rectangle{
	int x1,y1,x2,y2;
}rec[M];

struct SegTree{
	int count;
	int depth,amount,L,R,lv,rv;
}Tree[M*4];
void Update(int,int,int);
void Build(int root,int L,int R){
	Tree[root].amount = 0;
	Tree[root].lv = Tree[root].rv = 0;
	Tree[root].count = Tree[root].depth = 0;
	Tree[root].L = L;
	Tree[root].R = R;
	if(L == R - 1)  return ;
	Build(root<<1,L,(L+R)/2);
	Build((root<<1)+1,(L+R)/2,R);
}
void Insert(int root,int L,int R){
	if(Tree[root].L >= hash_y[L] && Tree[root].R <= hash_y[R]){
		Tree[root].count++;
		Update(root,L,R);
	}
	else {
		if(hash_y[L] < (Tree[root].L+Tree[root].R)/2){
			Insert(root<<1,L,R);
			Update(root,L,R);
		}
		if(hash_y[R] > (Tree[root].L+Tree[root].R)/2){
			Insert((root<<1)+1,L,R);
			Update(root,L,R);
		}
	}
}
void Delete(int root,int L,int R){
	if(Tree[root].L >= hash_y[L] && Tree[root].R <= hash_y[R]){
		Tree[root].count--;
		Update(root,L,R);
	}
	else {
		if(hash_y[L] < (Tree[root].L+Tree[root].R)/2){
			Delete(root<<1,L,R);
			Update(root,L,R);
		}
		if(hash_y[R] > (Tree[root].L+Tree[root].R)/2){
			Delete((root<<1)+1,L,R);
			Update(root,L,R);
		}
	}
}
void Update(int root,int L,int R){
	if(Tree[root].count > 0){
		Tree[root].depth = decod[Tree[root].R] - decod[Tree[root].L];
		Tree[root].amount = 1;
		Tree[root].lv = 1;
		Tree[root].rv = 1;
		Tree[root].amount = 1;
		return ;
	}
	if(Tree[root].L == Tree[root].R - 1) {
		
		if(Tree[root].count == 0){
			Tree[root].depth = 0;
			Tree[root].amount = 0;
			Tree[root].lv = 0;
			Tree[root].rv = 0;
		}
		return ;
	}
	if(Tree[root].count == 0){
		Tree[root].rv = Tree[(root<<1)+1].rv;
		Tree[root].lv = Tree[root<<1].lv;
		Tree[root].depth = Tree[root<<1].depth + Tree[(root<<1)+1].depth;
		Tree[root].amount = Tree[root<<1].amount + Tree[(root<<1)+1].amount
							- Tree[root<<1].rv * Tree[(root<<1)+1].lv;
	}
}
struct operation{
	In in;
	int x,lower_y,high_y;
}Event[M*4];

void input(){
	for(int i = 0;i < n;++i){
		cin>>rec[i].x1>>rec[i].y1>>rec[i].x2>>rec[i].y2;
		rec[i].x1 += M * 2;
		rec[i].x2 += M * 2;
		rec[i].y1 += M * 2;
		rec[i].y2 += M * 2;
	}
}
void Hash(){
	clr(hash_y,-1);
	for(int i = 0;i < n;++i){
		num_y[i*2] = rec[i].y1;
		num_y[i*2+1] = rec[i].y2;

		Event[i*2].in = lt;
		Event[i*2].x = rec[i].x1;
		Event[i*2].lower_y = rec[i].y1;
		Event[i*2].high_y = rec[i].y2;
		Event[i*2+1].in = rt;
		Event[i*2+1].x = rec[i].x2;
		Event[i*2+1].lower_y = rec[i].y1;
		Event[i*2+1].high_y = rec[i].y2;
	}
	sort(num_y,num_y+n*2);
	MaxY = 0;
	for(int i = 0;i < n*2;++i){
		if(hash_y[ num_y[i] ] == -1){
			hash_y[ num_y[i] ] = ++ MaxY;
			decod[MaxY] = num_y[i];
		}
	}
}
bool cmp(operation a,operation b){ return a.x < b.x; }
void solve(){
	input();
	Hash();
	Build(1,1,MaxY);
	sort(Event,Event+n*2,cmp);
	int ans = 0;
	int last_amount = 0,now_amount,last_depth = 0,now_depth = 0;
	for(int i = 0;i < n*2;++i){
		if(Event[i].in == lt) 
			Insert(1,Event[i].lower_y,Event[i].high_y);
		else
			Delete(1,Event[i].lower_y,Event[i].high_y);
		now_amount = Tree[1].amount;
		now_depth = Tree[1].depth;
		ans += last_amount * 2 * (i?(Event[i].x-Event[i-1].x):0);
		ans += abs(now_depth - last_depth);
		last_amount = now_amount;
		last_depth = now_depth;
	}
	cout<<ans<<endl;
}
int main(){
	while(cin>>n){
		solve();
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值