题目描述

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. Cocoapod-终端

    安装循序: Xcode->RVM->Ruby(安装过程中需要安装homebrew)->CocoaPats 参考文章: 安装地址:http://www.cnblogs.com/dagu ...

  2. protobuf编译工具使用

    1.下载,配置环境变量 下载地址:https://github.com/google/protobuf/releases,选择protoc-xxx-win64.zip下载 把.exe文件的位置加入到P ...

  3. Spring事务管理 —— readOnly只读事务

    事务是什么?事务是一个原子操作,由一系列动作组成.事务的原子性确保动作要么全部完成,要么完全不起作用. 下面来看一个项目中遇到的问题: 有这么一个需求,我们要查询一些数据,但是在查询这个数据之前我们要 ...

  4. 【C#并发】00概述

    摘自<C#并发编程经典实例>[美]Stephen Cleary 并发:同时做多件事情.终端用户利用并发功能,在输入数据库的同时相应用户输入.服务器应用并发,在处理第一个请求的同时响应第二个 ...

  5. quartz定时定时任务执行两次

    quartz框架没问题. 流程: sping-quartz配置 <?xml version="1.0" encoding="UTF-8"?> < ...

  6. 将List 分成n个长度由调用者指定的子List

    public static void main(String[] args) { List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8); ...

  7. 微信H5支付demo

    首先我们必须得在微信公众平台和微信商业平台那边配置好相关配置 1.注册微信服务号,开通微信支付权限绑定微信商业平台(这个具体怎么操作我就不说了) 2.获取应用(公众号)appid.应用(公众号)秘钥. ...

  8. 35)类和结构体类比---this

    那么,为啥  Test a(10)  , Test  b(20)   然后  我a.getI()  取到的是10,而不是20     就能将那个  10  给  a  对象的  m1    是因为有 ...

  9. 吴裕雄--天生自然TensorFlow高层封装:使用TensorFlow-Slim处理MNIST数据集实现LeNet-5模型

    # 1. 通过TensorFlow-Slim定义卷机神经网络 import numpy as np import tensorflow as tf import tensorflow.contrib. ...

  10. 吴裕雄--天生自然 pythonTensorFlow图形数据处理:输入数据处理框架

    import tensorflow as tf # 1. 创建文件列表,通过文件列表创建输入文件队列 files = tf.train.match_filenames_once("F:\\o ...