标签:hdu1542 hdu 1542 线段树 离散化 扫描线
2 10 10 20 20 15 15 25 25.5 0
Test case #1 Total explored area: 180.00
第一次做线段树+扫描线+离散化..当然是不会做的 甚至都没听说过
所以百度+查资料+看了n久 终于有了一点眉目。。
离散化是程序设计中一个非常常用的技巧,它可以有效的降低时间复杂度。其基本思想就是在众多可能的情况中“只考虑我需要用的值”。离散化可以改进一个低效的算法,甚至实现根本不可能实现的算法。要掌握这个思想,必须从大量的题目中理解此方法的特点。
在这里先按照x大小排序。(10,15,20,25)这样的话我们就知道矩形的长,然后就该求宽了。知道宽面积
不就是手到擒来嘛。至于求宽就是把y坐标离散化,然后开始建树,扫描求宽了。记得一次加入一个y坐标,其实
就是一个y=?的一条线、每添加两条线计算一次面积(如果添加1 2 3次计算两次面积求和),然后求和
这就是本题例题的四个扫描线。。第一次是标号为1的左边,第二次面积为红色,第三次为绿色,第四次就是蓝色
#include <stdio.h>
#include <algorithm>
using namespace std;
struct node1
{
double x,y1,y2,flag;//flag表示该边是入边还是出边
}c[205];
struct node2
{
double left,right,len,s;//s标记这条边是否完全覆盖
int l,r;
}d[205*4];
double y[205];//所有y坐标
bool cmp(node1 a,node1 b)
{
return a.x<b.x;
}
void build(int root,int l,int r)
{
d[root].l=l;
d[root].r=r;
d[root].left=y[l];
d[root].right=y[r];
d[root].len=0;
d[root].s=0;
if(l+1==r)
return ;
int mid=(l+r)/2;
build(root*2,l,mid);
build(root*2+1,mid,r);//不是mid+1,比如只有(10,15,20三个y坐标,应该出现三个范围(10 20)(10 15)(15 20))而不是(10 20)(10 15)
}
void cal(int root)
{
if(d[root].s>0)非0 完全覆盖
d[root].len=d[root].right-d[root].left;
else if(d[root].r-d[root].l==1)
d[root].len=0;
else
d[root].len=d[root*2].len+d[root*2+1].len;
}
void update(int root,node1 x)
{
if(d[root].left==x.y1&&d[root].right==x.y2)
{
d[root].s+=x.flag;
cal(root);
return ;
}
if(x.y1>=d[root*2].right) update(root*2+1,x);
else if(x.y2<=d[root*2+1].left) update(root*2,x);
else
{
node1 temp;
temp=x;
temp.y2=d[root*2].right;
update(root*2,temp);
temp=x;
temp.y1=d[root*2+1].left;
update(root*2+1,temp);
}
cal(root);
return ;
}
int main()
{
int n,ncase=1;
while(scanf("%d",&n)&&n)
{
int t=1;
for(int i=0;i<n;i++)
{
double x1,y1,x2,y2;
scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
c[t].x=x1,c[t].y1=y1,c[t].y2=y2,c[t].flag=1,y[t++]=y1;//入边<span style="white-space:pre"> </span>
c[t].x=x2,c[t].y1=y1,c[t].y2=y2,c[t].flag=-1,y[t++]=y2;//出边
}
sort(c+1,c+t,cmp);
sort(y+1,y+t);
build(1,1,t-1);
update(1,c[1]);
double sum=0;
for(int i=2;i<t;i++)
{
sum+=(c[i].x-c[i-1].x)*d[1].len;
update(1,c[i]);
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",ncase++,sum);
}
return 0;
}版权声明:本文为博主原创文章,未经博主允许不得转载。
hdu1542 Atlantis (线段树+扫描线+离散化)
标签:hdu1542 hdu 1542 线段树 离散化 扫描线
原文地址:http://blog.csdn.net/su20145104009/article/details/47703871