HDU 3265 - Posters

 

题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=3265

 

方法 : 线段树 + 扫描线

 

昨晚做了哈,想用个高效的方法(每个“回”字只用两次),貌似想搓了,不得已重新回到暴力(每个“回”字分成4份)。

 

另外,因为利用的是点化区间的方法。RE了一次,原因是没判断 if(p[i].y2>p[i].y1) , 题目中两者是有可能相等的。

   

#include
#include
#include
#include 
#define ll (v<<1)
#define rr (v<<1|1)
#define tmid ((l+r)>>1)
 
using namespace std;

const int maxn=50000;

struct Node{
	int x,y1,y2,f;
	Node(){}
	Node(int xx,int yy1,int yy2,int ff){
		x=xx,y1=yy1,y2=yy2,f=ff;
	}
}p[8*maxn+100];

int cmp(Node a,Node b){
	return a.x!=b.x?a.xb.f;
}

int rec[4*maxn+100],len[4*maxn+100];

void update(int val,int L,int R,int l,int r,int v){
	if(L<=l && r<=R) rec[v]+=val;
	else{
		if(L<=tmid) update(val,L,R,l,tmid,ll);
		if(R>tmid) update(val,L,R,tmid+1,r,rr);  
	}
	if(rec[v]) len[v]=r-l+1;
	else if(l==r) len[v]=0;
	else len[v]=len[ll]+len[rr];
}

int main(){
	int x1,x2,y1,y2,x3,x4,y3,y4;
	int n,cntp,i;
	__int64 sum;
	while(~scanf("%d",&n),n){
		cntp=0;
		while(n--){
			scanf("%d%d%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
			p[cntp++]=Node(x1,y1,y2,1);
			p[cntp++]=Node(x3,y1,y2,-1);
			p[cntp++]=Node(x4,y1,y2,1);
			p[cntp++]=Node(x2,y1,y2,-1);
			p[cntp++]=Node(x3,y1,y3,1);
			p[cntp++]=Node(x4,y1,y3,-1);
			p[cntp++]=Node(x3,y4,y2,1);
			p[cntp++]=Node(x4,y4,y2,-1);
		}
		sort(p,p+cntp,cmp);
		memset(rec,0,sizeof(rec));
		memset(len,0,sizeof(len));
		sum=0;
		for(i=0;ip[i].y1)update(p[i].f,p[i].y1,p[i].y2-1,0,maxn-1,1);
			sum+=(__int64)len[1]*(p[i+1].x-p[i].x); 
		}
		printf("%I64d\n",sum);
	}
	return 0;
} 


 

 

你可能感兴趣的:(ACM)