题目描述

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. Promoter complex|转录组水平RNA的复杂度|

    生命组学 Promoter complex Tata box识别位点 Enhancer加入之后增强转录 不确定性与确定性之间的关系,原因中存在这不确定性,但是结果表达又是确定的.因为promoter的 ...

  2. 爬虫—GEETEST滑动验证码识别

    一.准备工作 本次使用Selenium,浏览器为Chrome,并配置好ChromDriver 二.分析 1.模拟点击验证按钮:可以直接使用Selenium完成.    2.识别滑块的缺口位置:先观察图 ...

  3. Mongodb数据库(linux)——基础操作

    简介 MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统.它是非关系型数据库,但其结构与MySQL又很相似,mysql中的表格,在这里被称为集合,mysql表格内的数据是一 ...

  4. JavaScript学习笔记 - 进阶篇(6)- JavaScript内置对象

    什么是对象 JavaScript 中的所有事物都是对象,如:字符串.数值.数组.函数等,每个对象带有属性和方法. 对象的属性:反映该对象某些特定的性质的,如:字符串的长度.图像的长宽等: 对象的方法: ...

  5. 关于shopee平台接口(php)对接示例

    2018年8月之后,shopee开始使用新接口,需要进行授权操作 1.授权 public function getAuth(){ /** * @param ShopApiShopee $model * ...

  6. ES6之展开运算符

    本文介绍ES6新增的展开运算符(spread operator). 由上图可得,展开运算符负责拼装数组和对象,与之相反,解构赋值负责分解数组和对象. 由上图可得,展开运算符能和解构赋值一起发挥成更大的 ...

  7. 四、Shell脚本高级编程实战第四部

    一.比较两个数的大小 #!/bin/shread -p "Pls input two num:" a b[ -z "$a" ] || [ -z "$b ...

  8. regex(python)

    正则表达式 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/26 16:39 # @Author : jackendoff ...

  9. Python语言学习:模块

    一.模块 1. 模块(Module):以.py结尾的文件,包含python对象定义和python语句.使代码段更容易理解和使用. 模块分为两种:标准库(直接导入的库)和第三方库(需要下载安装的库). ...

  10. 【ccf-csp201512-5】矩阵

    click 试题编号: 201512-5 试题名称: 矩阵 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 创造一个世界只需要定义一个初状态和状态转移规则. 宏观世界的物体运动 ...