hdu1542矩阵的并 线段树+扫描线

时间:2023-11-24 20:20:56

求矩阵的并,也就是要求所有的面积。那可以吧总的图形按照矩阵来切割。使其为一块一块。

输入的时候用坐标表示,这里扫描线从下到上扫描。初始时让下面的边为1,上面的为-1;

用一条先从下面开始想上扫描。遇到更新线段树,加入该条边,为-1时就除去改变。

这样从下到上一遍扫描就可以得到线段的长度。从下到上的过程中,一旦遇到一条边,那就计算他的高度。

高度*长度就是面积。

/*
那叶子节点[l,l]的长度不就变成0,显然这是有问题的
线段树的每一个节点表示一段区间,[l,r]该区间表示LX[r+1]-LX[l]的长度
1___2___3___4___5离散后的状况
1 2 3 4 线段树中的每一个节点
*/
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 1005
double x[maxn<<];
struct seg
{
double l,r,h;
int f;
}s[maxn<<];
struct node
{
int cnt;//cnt表示该区间是否被完全覆盖 如果cnt==1表示被完全覆盖一次
//cnt=0表示为被完全覆盖 但是不代表未覆盖,cnt>1表示被多次完全覆盖
double len;
}tree[maxn*];
bool cmp(seg a,seg b)
{
return a.h<b.h;
}
int find(double val,int l,int r)
{
int left=l,right=r;
int mid;
while(left<=right)
{
mid=(left+right)/;
if(x[mid]==val)
return mid;
else if(x[mid]>val)
right=mid-;
else left=mid+;
}
return -;
}
void build(int l,int r,int rt)
{
if(l==r)
{
tree[rt].cnt=;
tree[rt].len=;
return ;
}
int m=(l+r)/;
build(lson);
build(rson);
}
void getlen(int rt,int l,int r)
{
if(tree[rt].cnt)//如果整一段被覆盖,直接求得长度
{
tree[rt].len=x[r+]-x[l];
}
else if(l==r)//叶子节点
tree[rt].len=;
else //不是叶子但也未整段覆盖,从儿子节点获得
tree[rt].len=tree[rt<<].len+tree[rt<<|].len;
}
void updata(int L,int R,int c,int l,int r,int rt)
{
if(l>=L&&R>=r)
{
tree[rt].cnt+=c;
getlen(rt,l,r);
return ;
}
int m=(l+r)/;
if(m>=L)
updata(L,R,c,lson);
if(R>m)
updata(L,R,c,rson);
getlen(rt,l,r);
}
int main()
{
int n,m,t,i,j,ff=;
double x1,x2,y1,y2;
while(scanf("%d",&n)!=EOF)
{
if(!n)
break;
m=;
for(i=;i<n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
s[m].l=x1;s[m].r=x2;s[m].h=y1;s[m].f=;
//下边界
s[m+].l=x1;s[m+].r=x2;s[m+].h=y2;s[m+].f=-;
//上边界
x[m]=x1;
x[m+]=x2;
m=m+;
}
sort(s,s+m,cmp);
sort(x,x+m);
int k=; for(i=;i<m;i++)//去重复
{
if(x[i]!=x[i-])
x[k++]=x[i];
} build(,k-,);
double ans=;
for(i=;i<m;i++)
{
int ll=find(s[i].l,,k-);//二分找位置
int rr=find(s[i].r,,k-)-;//因为这里表示的为线段 不是点。
updata(ll,rr,s[i].f,,k-,);
ans+=(s[i+].h-s[i].h)*tree[].len;
}
printf("Test case #%d\n",++ff);
printf("Total explored area: %.2lf\n\n",ans);
}
}