HDU-1828-Picture||POJ-1177 Picture(矩形的周长,扫描线)

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

题目链接:http://poj.org/problem?id=1177

题目大意:n个矩形放在一起,求覆盖的周长。

思路:扫描线,扫描一遍加和得出一条边的长度,同时维护两边的边长。注意节点表示的区间合并的时候,要注意左右两个线重合的部分要去掉(即pl,pr部分);

ACCode:

// luogu-judger-enable-o2
//#pragma comment(linker, "/STACK:1024000000,1024000000")
 
#include<stdio.h>
#include<string.h>
#include<math.h>
 
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
 
#define LL long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// 水印
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=1e4+10;
const int INF32=0x3f3f3f3f;
const LL INF64=0x3f3f3f3f3f3f3f3f;
const int MOD=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);

struct Line{
	double x1,y1,y2;int flag;
	Line(double _x1=0,double _y1=0,double _y2=0,int _flag=0){
		x1=_x1;y1=_y1;y2=_y2;flag=_flag;
	}
	friend int operator < (Line a,Line b){
		return a.x1<b.x1;
	}
};
struct Node{
	double len;int l,r,flag,num,lp,rp;
	Node(double _len=0,int _l=0,int _r=0,int _flag=0,int _num=0,int _lp=0,int _rp=0){
		len=_len;l=_l;r=_r;flag=_flag;num=_num;lp=_lp;rp=_rp;
	}
};
Line line[MAXN<<2];
Node tree[MAXN<<3];
double y[MAXN<<2];
int n;

int Location_x(double key,int l,int r){
	while(l<=r){
		int mid=(l+r)>>1;
		if(fabs(y[mid]-key)<EPS) return mid;
		else if(y[mid]>key) r=mid-1;
		else l=mid+1;
	}return -1;
}
void Build(int l,int r,int rt){
	tree[rt]=Node(0,l,r,0,0,0,0);
	if(l+1==r) return ;
	int mid=(l+r)>>1;
	Build(l,mid,rt<<1);Build(mid,r,rt<<1|1);
}
void PushUp(int rt){
	if(tree[rt].flag){//被完全覆盖 
		tree[rt].len=y[tree[rt].r]-y[tree[rt].l];
		tree[rt].lp=tree[rt].rp=1;
		tree[rt].num=1;
	}
	else if(tree[rt].l+1==tree[rt].r){
		tree[rt].len=0;
		tree[rt].lp=tree[rt].rp=0;
		tree[rt].num=0;
	}
	else{
		tree[rt].len=tree[rt<<1].len+tree[rt<<1|1].len;
		tree[rt].lp=tree[rt<<1].lp;tree[rt].rp=tree[rt<<1|1].rp;
		tree[rt].num=tree[rt<<1].num+tree[rt<<1|1].num-(tree[rt<<1].rp&tree[rt<<1|1].lp);
	}
}
void Update(int ql,int qr,int v,int rt){
//	cout<<"rt,ql,qr :"<<rt<<" "<<ql<<" "<<qr<<endl;
	if(ql==tree[rt].l&&qr==tree[rt].r){
		tree[rt].flag+=v;
		PushUp(rt);return ;
	}
	if(qr<=tree[rt<<1].r) Update(ql,qr,v,rt<<1);
	else if(ql>=tree[rt<<1|1].l) Update(ql,qr,v,rt<<1|1);
	else{
//		cout<<rt<<" "<<(rt<<1)<<" "<<(rt<<1|1)<<" "<<tree[rt<<1].r<<" "<<tree[rt<<1|1].l<<endl;
		Update(ql,tree[rt<<1].r,v,rt<<1);
		Update(tree[rt<<1|1].l,qr,v,rt<<1|1);
	}PushUp(rt);
}
int main(){
    while(~scanf("%d",&n)){
    	double x1,x2,y1,y2;
    	for(int i=1;i<=n;++i){
    		scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
    		line[i]=Line(x1,y1,y2,1);line[i+n]=Line(x2,y1,y2,-1);
    		y[i]=y1;y[i+n]=y2;
		}n*=2;sort(y+1,y+1+n);sort(line+1,line+1+n);
		int temp=2;
		for(int i=2;i<=n;++i){
			if(fabs(y[i]-y[i-1])>EPS) y[temp++]=y[i];
		}--temp;
//		for(int i=1;i<=n;++i){
//			cout<<line[i].x1<<" "<<line[i].y1<<" "<<line[i].y2<<" "<<line[i].flag<<endl;
//		}
//		for(int i=1;i<=temp;++i){
//			cout<<y[i]<<" ";
//		}cout<<endl;
		Build(1,temp,1);
//		for(int i=1;i<=(n<<1);++i){
//			cout<<"rt,l,r :"<<i<<" "<<tree[i].l<<" "<<tree[i].r<<endl;
//		}
		double ans=0,prelen=0;
		line[n+1]=line[n];
		for(int i=1;i<=n;++i){
			int l=Location_x(line[i].y1,1,temp),r=Location_x(line[i].y2,1,temp);
			Update(l,r,line[i].flag,1);
//			cout<<tree[1].len<<endl;
			ans+=fabs(tree[1].len-prelen);prelen=tree[1].len;
			ans+=(line[i+1].x1-line[i].x1)*(2*tree[1].num);
		}printf("%.0lf\n",ans);
	}
}

/*


*/

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值