您的位置:首页 > 理论基础 > 数据结构算法

HDU 1542 Atlantis 线段树矩形并 看别人的题解看了好多遍啊。 还是用了好久时间排错。

2013-06-26 16:34 453 查看
http://www.cnblogs.com/ka200812/archive/2011/11/13/2247064.html

用的是此博文所说的方法。。也参考了他的代码。。真的是排错排的好辛苦啊。。

。。下次把周长并的也做掉好了。。

/*
*以前一直云里雾理的Atantic,今天终于要自己动手写啦!!
*@author ipqhjjybj
*@data 20130626
*/

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>

#include <iostream>
#include <cmath>
#include <algorithm>
#include <numeric>
#include <utility>

#include <cstring>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <string>
using namespace std;

#define inf 0x3f3f3f3f
#define MAXN 1000
#define clr(x,k) memset((x),(k),sizeof(x))
#define cpy(x,k) memcpy((x),(k),sizeof(x))
#define Base 10000

typedef vector<int> vi;
typedef stack<int> si;
typedef vector<string> vs;
#define sz(a) int((a).size())
#define pb push_back
#define all(c) (c).begin(),(c).end()
#define rep(i,n) for(int i = 0;i < n;++i)
#define foreach(it,c) for(vi::iterator it = (c).begin();it != (c).end();++it)

#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
struct Line{
double y_down,y_up;
double x;
int flag; // flag=1表示左边,flag=2表示右边
bool operator<(const Line &a) const{
return (x<a.x);
}
}lines[250];
double yy[250],ty[250];
int tot,tyNum,yNum;
struct Tree{
int l,r;
int cover;
double c; //表示跨度
}tree[2000];
void Build(int left,int right,int rt){
tree[rt].l=left;
tree[rt].r=right;
tree[rt].c = 0.0;
tree[rt].cover=0;
if(left+1==right) //一条线段需要2个点。。不用接着往下建拉!!
return;
int mid=(left+right)>>1;
Build(left,mid,rt<<1);
Build(mid,right,rt<<1|1);
}
void fun(int i){
if(tree[i].cover)
tree[i].c=yy[tree[i].r]-yy[tree[i].l]; //如果cover大于1,那么整段都可用于与下一线段求并面积
else if(tree[i].l+1==tree[i].r) //叶子线段
tree[i].c=0;
else
tree[i].c=tree[2*i].c+tree[2*i+1].c; //很简单的dp
}
void Delete(int left,int right,int rt){
if(tree[rt].l>right||tree[rt].r<left)return;
if(tree[rt].l>=left && tree[rt].r<=right){
tree[rt].cover--;
fun(rt);
return;
}
Delete(left,right,rt<<1);
Delete(left,right,rt<<1|1);
fun(rt);
}
void Insert(int left,int right,int rt){
if(tree[rt].l>right||tree[rt].r<left)return;

if(tree[rt].l>=left && tree[rt].r<=right){
tree[rt].cover++;
fun(rt);
return;
}
Insert(left,right,rt<<1);
Insert(left,right,rt<<1|1);
//tree[rt].c = tree[rt<<1].c+tree[rt<<1|1].c;
fun(rt);
}

int CorresFind(int left,int right,double y){
int mid = (left+right)>>1;
if(left==right)return left;
if(yy[mid]==y)return mid;
else if(yy[mid] > y)
return CorresFind(left,mid-1,y);
else return CorresFind(mid+1,right,y);
}

int main(){
//freopen("1542.in","r",stdin);
int n;
double x1,y1,x2,y2;
int tt=0;
while(scanf("%d",&n)&& n){
yNum=tyNum=tot = 0;
for(int i = 0;i < n;i++){
scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);

lines[tot].y_down=y1,lines[tot].y_up=y2,lines[tot].x=x1,lines[tot].flag=1,tot++;
lines[tot].y_down=y1,lines[tot].y_up=y2,lines[tot].x=x2,lines[tot].flag=2,tot++;
ty[tyNum++]=y1;ty[tyNum++]=y2;
}
sort(ty,ty+2*n);
sort(lines,lines+2*n);

yy[++yNum]=ty[0];
for(int i= 1;i < tyNum;i++)
if(ty[i]!=ty[i-1])
yy[++yNum]=ty[i];
//yy从1到yNum
Build(1,yNum,1);

int l1,l2;
double ans=0.0;
for(int i=0;i<tot-1;i++){

l1 = CorresFind(1,yNum,lines[i].y_down);
l2 = CorresFind(1,yNum,lines[i].y_up);
if(lines[i].flag==1)
Insert(l1,l2,1);
else Delete(l1,l2,1);
ans+=tree[1].c*(lines[i+1].x-lines[i].x);
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",++tt,ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息