算法

线段树 + 离散化

思路

对\((x,y,h)\)的左右端点\(x,y\)进行离散化,离散化前的原值记为\(val[i]\),对每个矩形按高度\(h\)从小到大排序。

设离散化后的端点有\(M\)个,则对如图所示\(M-1\)个规则矩形编号为\([1,M-1]\),可以由\(h_{[i, i+1]}\times(val[i+1] - val[i])\)得出第\(i\)个矩形的面积。

开一颗区间为\([1,M-1]\)的线段树,按\(h\)从小到大依次对线段树区间覆盖,可以保证高的矩形覆盖了低的矩形的区间,具体操作为对离散化后的\((x,y,h)\),进行线段树\([x,y-1]\)区间覆盖\(h\)值,最终\(i\)点存储\(h_{[i,i+1]}\)的最大值。

\(h_{[i, i+1]}\)可以通过线段树单点查询\(i\)点求出。

答案:\(\sum_{i=1}^{M-1}h_{[i, i+1]}\times(val[i+1] - val[i])\)

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#define ll long long

using namespace std;
const int N = 80005;
int n, b[N], val[N];//b[]:离散化数组
struct Line { int x, y, h; }a[N];//存储每个矩形
bool cmp(Line a, Line b) { return a.h < b.h; }
int ans[N << 2];//线段树数组
#define ls (p << 1)
#define rs (p << 1 | 1)
#define mid ((l + r) >> 1)
void update(int p, int l, int r, int ul, int ur, int k)
{
    if(ul <= l && r <= ur) { ans[p] = k; return; }
    if(ans[p]) ans[ls] = ans[rs] = ans[p], ans[p] = 0;//区间覆盖直接下推
    if(ul <= mid) update(ls, l, mid, ul, ur, k);
    if(ur > mid) update(rs, mid + 1, r, ul, ur, k);
}
ll query(int p, int l, int r, int x)//单点查询
{
    if(l == r) return ans[p];
    if(ans[p]) ans[ls] = ans[rs] = ans[p], ans[p] = 0;//区间覆盖直接下推
    if(x <= mid) return query(ls, l, mid, x);
    if(x > mid) return query(rs, mid + 1, r, x);
}
#undef ls
#undef rs
#undef mid
int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].h);
        b[i] = a[i].x; b[n + i] = a[i].y;//离散化数组记录下所有x,y
    }
    sort(b + 1, b + 2 * n + 1);//排序
    int _n = unique(b + 1, b + 2 * n + 1) - (b + 1);//去重,_n为去重后x,y端点个数
    for(int i = 1; i <= n; i++)
        if(a[i].x != a[i].y)//x=y没有作用
    {
        int x = a[i].x, y = a[i].y;
        a[i].x = lower_bound(b + 1, b + _n + 1, a[i].x) - b;
        a[i].y = lower_bound(b + 1, b + _n + 1, a[i].y) - b;//离散化
        val[a[i].x] = x; val[a[i].y] = y;//原值
    }
    sort(a + 1, a + n + 1, cmp);//按h从小到大排序
    for(int i = 1; i <= n; i++)
        if(a[i].x != a[i].y)//防止y-1<x
            update(1, 1, _n - 1, a[i].x, a[i].y - 1, a[i].h);//更新,注意结点个数是_n-1,端点y要变成矩形区域y-1,可以画图理解一下,相当于把端点x右边的矩形区域编号为x
    ll res = 0;
    for(int i = 1; i < _n; i++)
        res += query(1, 1, _n - 1, i) * (val[i + 1] - val[i]);
    printf("%lld\n", res);
    return 0;
}

[题目] luogu P2061 [USACO07OPEN]城市的地平线City Horizon的更多相关文章

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

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

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

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

  3. Luogu_2061_[USACO07OPEN]城市的地平线City Horizon

    题目描述 Farmer John has taken his cows on a trip to the city! As the sun sets, the cows gaze at the cit ...

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

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

  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. Java提高篇之抽象类与接口

    接口和内部类为我们提供了一种将接口与实现分离的更加结构化的方法. 抽象类与接口是java语言中对抽象概念进行定义的两种机制,正是由于他们的存在才赋予java强大的面向对象的能力.他们两者之间对抽象概念 ...

  2. [Luogu4986] 逃离

    Description 给定次数为 \(n\) 的函数 \(A(x),B(x),C(x)\),求 \(A^2(x)+B^2(x)-C^2(x)\) 在 \([L,R]\) 的零点.\(n\leq 10 ...

  3. [转]angular2封装material2对话框组件

    本文转自:https://www.jianshu.com/p/da9978e25566 1. 说明 angular-material2自身文档不详,控件不齐,使用上造成了很大的障碍.这里提供一个方案用 ...

  4. JavaSE-基础语法(一)--数据类型及包装类

    一.JavaSE-基础语法(一) 一.数据类型 二.变量常量 三.流程控制语句 四.数组 一.数据类型 java语言的数据类型包括两种,基本数据类型和引用数据类型. (1).基本数据类型:变量名指向具 ...

  5. MySQL ORDER BY主键id加LIMIT限制走错索引

    背景及现象 report_product_sales_data表数据量2800万: 经测试,在当前数据量情况下,order by主键id,limit最大到49的时候可以用到索引report_produ ...

  6. Django Rest Framework之权限

    基本代码结构 url.py: from django.conf.urls import url, include from app import views urlpatterns = [ url(r ...

  7. linux shell脚本之-变量极速入门与进阶(1)

    1,如果创建shell脚本? 使用任意文本编辑软件,一般为vim,创建.sh结尾的文件,在文件的最开头用 #!/bin/bash 注明shell的类型 如: ghostwu@dev:~/linux/s ...

  8. 10个最佳ES6特性

    译者按: 人生苦短,我用ES6. 原文: Top 10 ES6 Features Every Busy JavaScript Developer Must Know 译者: Fundebug 为了保证 ...

  9. Python全栈学习_day009知识点

    今日大纲: . 函数的初识 . 函数的返回值 . 函数的参数 1. 函数的初识 统计字符串s的总个数(不能用len) s='fkahfkahofijalkfkadhfkjadhf' count = f ...

  10. SD从零开始67-70 后勤信息系统中的标准分析, 信息结构, 信息的更新规则, 建立统计数据

    SD从零开始67 后勤信息系统中的标准分析 标准分析中的报表Reporting in Standard Analyses 标准分析为高质量的表达和分析LIS中的数据基础提供了大量的功能: 当你决定了一 ...