题目地址: 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;
}