标签:des style blog http color os io strong
|
Mean:
在二维平面中,给你一些矩形的左下坐标(x1,y1)和右上坐标(x2,y2),让你求这些矩形面积的并。
analyse:
我们在y轴方向上维护一棵线段树。该线段树的模型是区间覆盖,即应该对像某个区间有没有被覆盖这样的查询,以及添加覆盖和删除覆盖这样的操作---也就是将矩形的左右两边界看作对y轴的覆盖来处理。我们将所有矩形的左右边界按照x坐标升序排序。每个矩形的左边界执行对y轴的覆盖操作,右边界执行对x轴的删除覆盖操作。
每次插入一条线段的时候,我们判断cover值(覆盖的次数),如果>0那么就算面积。
如图:

初始时每条线段的cover都为0;
线段1插入后,所对应的区间cover变为1,当第二条线段插入时,我们先判断一下该区间上的cover值,发现有一段cover是大于0的,所以就将对应的面积(蓝色部分)加入ans中,此时线段2下半部分的cover值变为2,上部分的cover值变为1,还要把线段1的上部分的x坐标更新为线段2的x值;
当第三条直线插入时,同样的道理,加入的是黄色部分的面积;第四条进入时,加入的是紫色部分的面积。
这样,我们只需要在插入前先计算面积,当所有线段插入结束,answer也就出来了。
所以我们的线段树只需要两个函数:build和insert函数。
Time complexity:O(n*logn)
Source code:
//Memory Time
// 1347K 0MS
// by : Snarl_jsb
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<vector>
#include<queue>
#include<stack>
#include<iomanip>
#include<string>
#include<climits>
#include<cmath>
#define MAX 1100
#define LL long long
using namespace std;
double y[2*MAX];
struct LINE
{
double x,y_down,y_up;
int flag; // 左线段or右线段
};
LINE line[MAX<<1];
struct Tree
{
int x;
int cover; // 覆盖次数
bool flag; // 是否为叶子节点
int y_up,y_down;
};
Tree tree[(1010<<2)*4];
bool cmp(LINE a,LINE b)
{
return a.x<b.x;
}
void build(int l,int r,int x)
{
tree[x].x=-1; // -1表示该区间没有线段
tree[x].cover=0;
tree[x].flag=false;
tree[x].y_up=y[r];
tree[x].y_down=y[l];
if(l+1==r) // 叶子结点: (1,2) (2,3) (3,4) (4,5)....
{
tree[x].flag=true;
return;
}
int tmp=x<<1;
int mid=(l+r)>>1;
build(l,mid,tmp);
build(mid,r,tmp+1);;
}
double insert(int i,double x,double l,double r,int flag)
{
if(r<=tree[i].y_down||l>=tree[i].y_up) //要插入的线段不在该区间
return 0;
if(tree[i].flag) // 叶子节点
{
if(tree[i].cover>0) // 需要求并面积
{
double temp_x=tree[i].x;
double ans=(x-temp_x)*(tree[i].y_up-tree[i].y_down); // 宽*高
tree[i].x=x; // 更新树中的x值
tree[i].cover+=flag;
return ans;
}
else
{
tree[i].cover+=flag;
tree[i].x=x;
return 0;
}
}
double ans1,ans2;
int tmp=i<<1;
ans1=insert(tmp,x,l,r,flag);
ans2=insert(tmp+1,x,l,r,flag);
return ans1+ans2;
}
int main()
{
// freopen("cin.txt","r",stdin);
// freopen("cout.txt","w",stdout);
int T;
cin>>T;
double x1,y1,x2,y2;
while(T--)
{
int n;
cin>>n;
int index=1;
for(int i=1;i<=n;i++)
{
scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
y[index]=y1;
line[index].x=x1;
line[index].y_down=y1;
line[index].y_up=y2;
line[index].flag=1;
index++;
y[index]=y2;
line[index].x=x2;
line[index].y_down=y1;
line[index].y_up=y2;
line[index].flag=-1;
index++;
}
index--;
double ans=0.0;
sort(line+1,line+1+index,cmp);
sort(y+1,y+1+index);
build(1,index,1);
for(int i=1;i<=index;i++)
{
ans+=insert(1,line[i].x,line[i].y_down,line[i].y_up,line[i].flag);
}
printf("%.0lf\n",ans);
}
return 0;
}
线段树 : 求矩形面积的并 ---- hnu : 12884 Area Coverage,布布扣,bubuko.com
线段树 : 求矩形面积的并 ---- hnu : 12884 Area Coverage
标签:des style blog http color os io strong
原文地址:http://www.cnblogs.com/acmer-jsb/p/3904794.html