题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=1828
方法: 线段树 + 扫描线
用扫描线的思想,很容易就想到,这题扫的主要是外围端点数量。
以Y坐标轴作为扫描线,向X轴右方向进行扫描。
每次扫描线上的纵向长度改变时(新的出度或者入度),即周长相应地进行变化,于是我们加上这个变化。
每次得到端点的数量,这个数量乘以x轴上的跨度,即得到了每次扫描后新增加的横轴周长。
关于端点,入度进行记录,出度相应地进行删除。
=============================================================================================
PS:
有了之前一题扫描线的经历,这题看了第一眼就有想法了。
敲得可谓是“轻车熟路”。。。 但最后连sample数据都过不去。。。 囧。。。
一直以为是算法出错。。。 查了半天,发现竟然是细节问题。。。囧。。。
1. 求len长度时,将 r - l + 1 写成了 l - r - 1,导致出现负数。。。又刚好用了abs(),所以很久才发现。。。
2. 宏定义 rr 写成了 ( v<<1 ) 少加1了。。。
3. 没有注意看,题目最后说了句:“Please process to the end of file.”。。。 悲剧地只针对一组测试数据去写。。。贡献了一个WA。。。
小错也重要呀~
==============================================================================================
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll (v<<1)
#define rr (v<<1|1)
#define tmid ((l+r)>>1)
using namespace std;
struct Point{
int x,y1,y2,f;
Point(){}
Point(int a,int b,int c,int d){x=a,y1=b,y2=c,f=d;}
bool friend operator<(Point a,Point b){
return a.x<b.x;
}
}p[10100];
int len[80010];
int seg_num[80010];
bool ls[80010],rs[80010];
int tree[80010];
void update(int L,int R,int f,int l,int r,int v){
if(L<=l && r<=R){
tree[v]+=f;
}
else{
if(L<=tmid) update(L,R,f,l,tmid,ll);
if(R>tmid) update(L,R,f,tmid+1,r,rr);
}
if(tree[v]>0){
ls[v]=rs[v]=true;
seg_num[v]=2;
len[v]=r-l+1;
}
else if(l==r){
ls[v]=rs[v]=false;
seg_num[v]=len[v]=0;
}
else{
ls[v]=ls[ll];
rs[v]=rs[rr];
seg_num[v]=seg_num[ll]+seg_num[rr];
if(rs[ll] && ls[rr]) seg_num[v]-=2;
len[v]=len[ll]+len[rr];
}
}
int main(){
int n,i,res,last;
int x1,y1,x2,y2,tol,a,b,c,d;
int lm,rm;
while(~scanf("%d",&n)){
tol=0;
lm=10000,rm=-10000;
while(n--){
scanf("%d%d%d%d",&a,&b,&c,&d);
x1=min(a,c),x2=max(a,c);
y1=min(b,d),y2=max(b,d);
p[tol++]=Point(x1,y1,y2,1);
p[tol++]=Point(x2,y1,y2,-1);
if(lm>y1) lm=y1;
if(rm<y2) rm=y2;
}
sort(p,p+tol);
res=last=0;
for(i=0;i<tol;i++){
if(p[i].y1<p[i].y2) update(p[i].y1,p[i].y2-1,p[i].f,lm,rm-1,1);
res+=seg_num[1]*(p[i+1].x-p[i].x);
res+=abs(len[1]-last);
// cout<<seg_num[1]<<" "<<len[1]<<endl;
last=len[1];
}
printf("%d\n",res+len[1]);
}
return 0;
}