题目描述

Farmer John has taken his cows on a trip to the city! As the sun sets, the cows gaze at the city horizon and observe the beautiful silhouettes formed by the rectangular buildings.

The entire horizon is represented by a number line with N (1 ≤ N ≤ 40,000) buildings. Building i's silhouette has a base that spans locations Ai through Bi along the horizon (1 ≤ Ai < Bi ≤ 1,000,000,000) and has height Hi (1 ≤ Hi ≤ 1,000,000,000). Determine the area, in square units, of the aggregate silhouette formed by all N buildings.

约翰带着奶牛去都市观光。在落日的余晖里,他们看到了一幢接一幢的摩天高楼的轮廓在地平线 上形成美丽的图案。以地平线为 X 轴,每幢高楼的轮廓是一个位于地平线上的矩形,彼此间可能有 重叠的部分。奶牛一共看到了 N 幢高楼,第 i 幢楼的高度是 Hi,两条边界轮廓在地平线上的坐标是 Ai 到 Bi。请帮助奶牛们计算一下,所有摩天高楼的轮廓覆盖的总面积是多少。

输入输出格式

输入格式

第一行一个整数N,然后有N行,每行三个正整数ai、bi、Hi。

输出格式

一个数,数列中所有元素的和。

样例

INPUT

4

2 5 1

9 10 4

6 8 2

4 6 3

OUTPUT

16

HINT

N<=40000 , a、b、k<=10^9 。

SOLUTION

离散化+线段树

瞄一眼数据范围,不用想就知道一定要离散化,对于我来说这种离散化方法还是头一次用(就是这离散化调得我大头疼。)然后区间最大值?果断线段树啊。

其实对于题目给定的\(a_i,b_i\)画个图就可以看出来,由于我们线段树处理的是点,所以我们只要覆盖\(a_i\)到\(b_i-1\)的点就行了。

而且因为对于每一段区间我们保留的是最大的\(h\),所以只要再修改以前,以\(h\)为关键字,再对每栋楼从小到大排个序就可以直接覆盖了。

如何计算呢?

因为我们离散化之后就剩下了一堆关键点\(p\),然后对于每一个\(p_i\)只要把\(i\)点的高度乘以\((p_{i+1}-p_i)\)(前面有说,因为不包括右端点)就可以得到面积了。

然后记得push_down的时候一定要先判断\(s[id]\)是否非零,不然就把原来存在的值清除了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N=40100;
int n,p[N<<1],s[N<<3];
LL ans=0;
struct BD{int a,b,h;}bld[N];
inline int read(){
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') {x=x*10+ch-48;ch=getchar();}
return x*f;}
bool cmp(BD x,BD y) {return x.h<y.h;}
void pushdown(int id,int l,int r){
if (l==r) return;
s[id<<1]=s[id];s[id<<1|1]=s[id];s[id]=0;}
void change(int id,int l,int r,int L,int R,int H){
if (s[id]) pushdown(id,l,r);
if (l>=L&&r<=R) {s[id]=H;return;}
int mid=(l+r)>>1;
if (mid>=L) change(id<<1,l,mid,L,R,H);
if (mid<R) change(id<<1|1,mid+1,r,L,R,H);
}
int findh(int id,int l,int r,int ND){
if (l==r) {return s[id];}
if (s[id]) pushdown(id,l,r);
int mid=(l+r)>>1;
if (mid>=ND) return findh(id<<1,l,mid,ND);
else return findh(id<<1|1,mid+1,r,ND);
}
int main(){
int i,j;
n=read();for (i=1;i<=n;++i) {
bld[i].a=read();bld[i].b=read();bld[i].h=read();
p[i*2-1]=bld[i].a;p[i*2]=bld[i].b;}
sort(p+1,p+1+2*n);
int cnt=2*n;//int cnt=unique(p+1,p+1+2*n)-p;
sort(bld+1,bld+1+n,cmp);
memset(s,0,sizeof(s));
for (i=1;i<=n;++i){
int L=lower_bound(p+1,p+1+cnt,bld[i].a)-p;
int R=lower_bound(p+1,p+1+cnt,bld[i].b)-p;
// printf("L:%d R:%d H:%d\n",L,R-1,bld[i].h);
change(1,1,cnt,L,R-1,bld[i].h);
}
for (i=1;i<cnt;++i){
LL H=findh(1,1,cnt,i);
ans=ans+H*(p[i+1]-p[i]);
// printf("%lld %d;",H,(p[i+1]-p[i]));
// printf("%d %d\n",p[i],p[i+1]);
}
printf("%lld\n",ans);
return 0;
}

Luogu_2061_[USACO07OPEN]城市的地平线City Horizon的更多相关文章

  1. bzoj1645 / P2061 [USACO07OPEN]城市的地平线City Horizon(扫描线)

    P2061 [USACO07OPEN]城市的地平线City Horizon 扫描线 扫描线简化版 流程(本题为例): 把一个矩形用两条线段(底端点的坐标,向上长度,添加$or$删除)表示,按横坐标排序 ...

  2. 线段树+扫描线【bzoj1645】[USACO07OPEN]城市的地平线City Horizon

    Description 约翰带着奶牛去都市观光.在落日的余晖里,他们看到了一幢接一幢的摩天高楼的轮廓在地平线 上形成美丽的图案.以地平线为 X 轴,每幢高楼的轮廓是一个位于地平线上的矩形,彼此间可能有 ...

  3. [题目] luogu P2061 [USACO07OPEN]城市的地平线City Horizon

    算法 线段树 + 离散化 思路 对\((x,y,h)\)的左右端点\(x,y\)进行离散化,离散化前的原值记为\(val[i]\),对每个矩形按高度\(h\)从小到大排序. 设离散化后的端点有\(M\ ...

  4. 洛谷 P2061 [USACO07OPEN]城市的地平线City Horizon

    简化版的矩形面积并,不用线段树,不用离散化,代码意外的简单 扫描线,这里的基本思路就是把要求的图形竖着切几刀分成许多矩形,求面积并.(切法就是每出现一条与y轴平行的线段都切一刀) 对于每一个切出来的矩 ...

  5. 1645: [Usaco2007 Open]City Horizon 城市地平线

    1645: [Usaco2007 Open]City Horizon 城市地平线 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 315  Solved: ...

  6. BZOJ_1654_[Usaco2007 Open]City Horizon 城市地平线_扫描线

    BZOJ_1654_[Usaco2007 Open]City Horizon 城市地平线_扫描线 Description N个矩形块,交求面积并. Input * Line 1: A single i ...

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

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

  8. bzoj1645 [Usaco2007 Open]City Horizon 城市地平线

    Description Farmer John has taken his cows on a trip to the city! As the sun sets, the cows gaze at ...

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

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

随机推荐

  1. 在storyboard中给控制器添加导航栏控制器和标签控制器

    1.选中目标控制器 2.选择xcode的工具栏中的"Editor"->"Embed in"->"Navigation Controller ...

  2. geodjango七日学习笔记 (7.30整理本地笔记上传到网络)

    第一天进行到现在,在开端的尾巴,想起来写一个学习笔记, 开发环境已搭好,用的是pycharm 环境是本机已有的interpreter python3.7   接下来要做的是新建一个geodjango项 ...

  3. NGDC|BIGD

    生命组学 生命起源经过复杂演化诞生了大量生物体及其基因组. 现今NCBI最大的基因组: 植物:糖松27.6G 动物:墨西哥蝾螈32.4G 大数据能做什么? 大数据时代如同大航海时代一样,需要具有与时代 ...

  4. dht算法原理描述

    dht原理 dht是P2P网络(结构化P2P)核心路由算法,主要是利用一致性hash,把节点和资源都表示成一个hash值,放入到这个大的hash环中,每个节点负责路由靠近它的资源. 一.重要概念:  ...

  5. Python 学习笔记:根据输入年月获取该月的第一天和最后一天

    目的: 给定一个时间,比如:2020.02,要求返回所输入月份的第一天及最后一天,比如:('2020.02.01', '2020.02.29') 参考博客:https://blog.csdn.net/ ...

  6. 借助Nginx搭建反向代理服务器

    一.反向代理:Web服务器的"经纪人" 1.1 反向代理初印象 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网 ...

  7. 给Office文档添加水印效果【测试有效】

    private void button1_Click(object sender, EventArgs e) { string test1 = "C:\\test.docx";// ...

  8. Python——Pandas 时间序列数据处理

    介绍 Pandas 是非常著名的开源数据处理库,我们可以通过它完成对数据集进行快速读取.转换.过滤.分析等一系列操作.同样,Pandas 已经被证明为是非常强大的用于处理时间序列数据的工具.本节将介绍 ...

  9. Intellij IDEA中mybatis-generator自动生成

    一.在maven工程中的resource中创建generatorConfig.xml 二.配置generatorConfig.xml: <?xml version="1.0" ...

  10. 关于前端html5的总结

    简介 HTML5 是HTML语言的第5次重大修改产生的新的HTML语言版本 HTML5 是W3C组织和众多主要浏览器厂商以及众多开发者共同努力的结果,得之不易 HTML5 主要改进包括:增加新的HTM ...