【题目描述】:在地平线上有n个建筑物。每个建筑物在地平线上可以看成一个下边界和地平线重合的矩形。每个建筑物有三个描述(Li ,Ri,Hi),分别表示该建筑物的左边界,右边界,高度。输出输出这些建筑物在地平线上投影的总面积。

【输入文件】

输入文件horizon.in第一行包含一个整数n,表示有n个建筑物。

以下下n.行,每行三个整数Li ,Ri,Hi。

【输出文件】

输出这些建筑物在地平线上投影的总面积

【样例】

horizon.in   horizon.out   4

2 5 1

9 10 4

6 8 2

4 6 3

16

【限制】

100%的数据满足:1<=n<=40,000

1 ≤ Li < Ri ≤ 1,000,000,000

1 ≤ Hi ≤ 1,000,000,000

区间问题容易想到线段树解决。最开始想枚举每个区间最左和最右两个矩形的位置关系(相离、相切、相交、内含)并在建树时即统计面积,但在写的发现很难实现…

正解是区间修改,每加入一个矩形,就二分找到它所覆盖的区间,并改变该区间的覆盖高度

在建树时注意因为矩形边长>=1,右界需要取中点,且叶子节点的左右端点相差为1;

此题的考点:

1、区间中需要处理的点稀疏而区间很长时,需要离散化(矩形的端点只有80000个,区间长10亿);

2、区间修改操作;

#include<cstdio>
#include<algorithm>
using namespace std;
int n;
int ans,t;
struct node{
int left,right;
int c;
}tree[*];
struct edge{
int left,right,h;
}a[];
int p[*];
bool cmp(edge e1,edge e2)
{
return e1.h<e2.h;
}
int erfen(int l,int r,int x)
{
while(l<=r)
{
int mid=(l+r)/;
if(p[mid]==x) return mid;
else if(p[mid]>x) r=mid-;
else l=mid+;
}
return ;
}
void change(int now,int l,int r,int x)
{
if(tree[now].right<l||tree[now].left>r) return;
if(tree[now].left>=l&&tree[now].right<=r)
{
tree[now].c=x;
return;
}
int mid=(tree[now].left+tree[now].right)/;
if(tree[now].c) {
tree[now*].c=tree[now].c;
tree[now*+].c=tree[now].c;
tree[now].c=;
} if(mid>=r) change(now*,l,r,x);
else if(mid<=l) change(now*+,l,r,x);
else {
change(now*,l,r,x); change(now*+,l,r,x);
}
}
void built(int now,int l,int r)
{
tree[now].left=l;
tree[now].right=r;
tree[now].c=;
if(l==r-) return;
built(now*,l,(l+r)/);
built(now*+,(l+r)/,r);//*****右界要包括mid
}
void quest(int now)
{
if(tree[now].c)
{
ans+=(p[tree[now].right]-p[tree[now].left])*tree[now].c;
return;
}
if(tree[now].right==tree[now].left+) return;
quest(now*);
quest(now*+);
}
int main()
{
freopen("horizon.in","r",stdin);
freopen("horizon.out","w",stdout);
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d%d%d",&a[i].left,&a[i].right,&a[i].h);
p[++t]=a[i].left;
p[++t]=a[i].right;
}
sort(p+,p++*n);
sort(a+,a+n+,cmp);
built(,,n*);
for(int i=;i<=n;i++)
{
int l=erfen(,*n,a[i].left);
int r=erfen(,*n,a[i].right);
change(,l,r,a[i].h);
}
quest();
printf("%d",ans);
}

| 线段树-地平线horizon的更多相关文章

  1. 【BZOJ1645】[Usaco2007 Open]City Horizon 城市地平线 离散化+线段树

    [BZOJ1645][Usaco2007 Open]City Horizon 城市地平线 Description Farmer John has taken his cows on a trip to ...

  2. 【BZOJ】1645: [Usaco2007 Open]City Horizon 城市地平线(线段树+特殊的技巧)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1645 这题的方法很奇妙啊...一开始我打了一个“离散”后的线段树.............果然爆了. ...

  3. bzoj 1645: [Usaco2007 Open]City Horizon 城市地平线【线段树+hash】

    bzoj题面什么鬼啊-- 题目大意:有一个初始值均为0的数列,n次操作,每次将数列(ai,bi-1)这个区间中的数与ci取max,问n次后元素和 离散化,然后建立线段树,每次修改在区间上打max标记即 ...

  4. [BZOJ1645][Usaco2007 Open]City Horizon 城市地平线 线段树

    链接 题意:N个矩形块,交求面积并. 题解 显然对于每个 \(x\),只要求出这个 \(x\) 上面最高的矩形的高度,即最大值 将矩形宽度离散化一下,高度从小到大排序,线段树区间set,然后求和即可 ...

  5. 离散化+线段树 POJ 3277 City Horizon

    POJ 3277 City Horizon Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 18466 Accepted: 507 ...

  6. poj City Horizon (线段树+二分离散)

    http://poj.org/problem?id=3277 City Horizon Time Limit: 2000MS   Memory Limit: 65536K Total Submissi ...

  7. 线段树 扫描线 L - Atlantis HDU - 1542 M - City Horizon POJ - 3277 N - Paint the Wall HDU - 1543

    学习博客推荐——线段树+扫描线(有关扫描线的理解) 我觉得要注意的几点 1 我的模板线段树的叶子节点存的都是 x[L]~x[L+1] 2 如果没有必要这个lazy 标志是可以不下传的 也就省了一个pu ...

  8. [POJ] 3277 .City Horizon(离散+线段树)

    来自这两篇博客的总结 http://blog.csdn.net/SunnyYoona/article/details/43938355 http://m.blog.csdn.net/blog/mr_z ...

  9. POJ 3277 City Horizon(叶子节点为[a,a+1)的线段树+离散化)

    网上还有用unique函数和lowerbound函数离散的方法,可以百度搜下题解就有. 这里给出介绍unique函数的链接:http://www.cnblogs.com/zhangshu/archiv ...

随机推荐

  1. react中input自动聚焦问题

    input自动聚焦问题 在react中可以使用refs解决这个问题,首先看一下refs的使用场景: (1)处理焦点.文本选择或媒体控制. (2)触发强制动画. (3)集成第三方 DOM 库. 使用re ...

  2. [面试] mysql 面试题

    最近在准备面试,mysql 实在是不熟悉,就先摘录一些网上的面试题来看一下. 1. MyISAM 和 InnoDB 区别? InnoDB 支持事务处理,支持更大的并发update 和 insert 操 ...

  3. 在c:forEach与s:iterator里面使用if标签判断当前位置是否为2的倍数

    在c:forEach与s:iterator里面使用if标签判断当前位置是否为2的倍数 c:forEach: <c:forEach var="workflow" items=& ...

  4. SQL Server - AS

    AS 是给现有的字段名/表名指定一个别名的意思.

  5. oracle用命令创建表空间、用户,并为用户授权、收回权限。

    oracle中如何删除用户? Oracle中使用DROP USER来删除用户,如果使用DROP USER CASCADE那么用户的对象也同时被删除掉.为了达到删除用户的效果而又不影响对用户下的对象的使 ...

  6. Lua中的userdata

    [话从这里说起] 在我发表<Lua中的类型与值>这篇文章时,就有读者给我留言了,说:你应该好好总结一下Lua中的function和userdata类型.现在是时候总结了.对于functio ...

  7. selenium之 webdriver与三大浏览器版本映射表(更新至v2.29)

    1.chrome浏览器 chromedriver版本 支持的Chrome版本 v2.29 v56-58 v2.28 v55-57 v2.27 v54-56 v2.26 v53-55 v2.25 v53 ...

  8. day18正则及re模块

    在线测试工具 http://tool.chinaz.com/regex/ 正则表达式本身和python语言没什么联系,只是匹配字符串内容的一种规则:详见:http://www.cnblogs.com/ ...

  9. Nhibernate 使用 (一)

    一:介绍 NHibernate 是一个基于.Net 的针对关系型数据库的对象持久化类库.Nhibernate 来源于非常优秀的基于Java的Hibernate 关系型持久化工具.NHibernate ...

  10. Notes for "Python in a Nutshell"

    Introduction to Python Wrap C/C++ libraries into Python via Cython and CFFI. Python implementations ...