使用扫描线操作
附上代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 50004*2;
struct node{
int l,r;
int len; //有效长度
int lf,rf; //实际的左右端点。
int numseg; //所包含的区间数量,如三条[1,2],[2,3],[4,5]线段被覆盖,则line=2,
//因为 [1,2],[2,3]是连续的。这个是用来辅助计算横边的
int cover;
bool lcover,rcover;
}segTree[maxn<<2];
struct Line{
int y;
int x1,x2;
int f;
}line[maxn];
bool cmp(Line a,Line b){
return a.y<b.y;
}
int x[maxn];
void build(int i,int l,int r){
segTree[i].l=l;
segTree[i].r=r;
segTree[i].lf=x[l];
segTree[i].rf=x[r];
segTree[i].len=0;
segTree[i].numseg=0;
segTree[i].cover=0;
segTree[i].lcover=segTree[i].rcover=false;
if(l+1==r) return;
int mid=l+r>>1;
build(i<<1,l,mid);
build(i<<1|1,mid,r);
}
void cal_len(int i){
if(segTree[i].cover>0){
segTree[i].len=segTree[i].rf-segTree[i].lf;
segTree[i].numseg=1;
segTree[i].lcover=segTree[i].rcover=true;
return;
}
if(segTree[i].l+1==segTree[i].r){
segTree[i].len=segTree[i].numseg=segTree[i].lcover=segTree[i].rcover=0;
}else{
segTree[i].len=segTree[i<<1].len+segTree[i<<1|1].len;
segTree[i].lcover=segTree[i<<1].lcover;
segTree[i].rcover=segTree[i<<1|1].rcover;
segTree[i].numseg=segTree[i<<1].numseg+segTree[i<<1|1].numseg;
if(segTree[i<<1].rcover&&segTree[i<<1|1].lcover) segTree[i].numseg--;
}
}
void update(int i,Line e){
if(segTree[i].lf==e.x1&&segTree[i].rf==e.x2){
segTree[i].cover+=e.f;
cal_len(i);
return;
}
if(e.x2<=segTree[i<<1].rf) update(i<<1,e);
else if(e.x1>=segTree[i<<1|1].lf) update(i<<1|1,e);
else{
Line tmp=e;
tmp.x2=segTree[i<<1].rf;
update(i<<1,tmp);
tmp=e;
tmp.x1=segTree[i<<1|1].lf;
update(i<<1|1,tmp);
}
cal_len(i);
}
int main(){
int x1,y1,x2,y2;
int n;
while(scanf("%d",&n)==1)
{
int t=0;
for(int i=0;i<n;i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
line[t].x1=x1;
line[t].x2=x2;
line[t].y=y1;
line[t].f=1;
x[t++]=x1;
line[t].x1=x1;
line[t].x2=x2;
line[t].y=y2;
line[t].f=-1;
x[t++]=x2;
}
sort(line,line+t,cmp);
sort(x,x+t);
int m=unique(x,x+t)-x;//合并相同元素,这里一点要合并相同元素,否则会WA.
build(1,0,m-1);
int ans=0;
int last=0;
for(int i=0;i<t-1;i++){
update(1,line[i]);
ans+=segTree[1].numseg*2*(line[i+1].y-line[i].y);
ans+=abs(segTree[1].len-last);
last=segTree[1].len;
}
update(1,line[t-1]);
ans+=abs(segTree[1].len-last);
printf("%d\n",ans);
}
return 0;
}