Description

平面上有\(n\)个位置\(1\dots n\),第\(i\)个位置有一个高为\(H_i\)的楼房;所有\(H\)初始值为\(0\)。每次修改一个\(H_i\),求修改后从\((0,0)\)点可以看到多少楼房。\(n,m\leq10^5\)。

Solution

线段树。

首先可以发现某个楼房能够被看到当且仅当它的顶点斜率>所有前面的楼房顶点的斜率。

只记录斜率,把“比前面所有数都大的数”称为“优数”,那么答案即为“优数”的个数

那么线段树每个节点维护最大值\(max\)和区内“优数”的个数\(ans\)。

先考虑查询。我们把查询写成\(q(o, x)​\)表示查询\([l_o,r_o]​\)区间(即结点\(o​\)代表的区间)内比\(x​\)大的“优数”的个数。

如果\(x\)大于等于\(max_{lson}\),那么\(q(o,x)=q(rson, x)\)。显然。

否则,\(q(o,x)=ans_o - (ans_{lson}-q(lson, x))\),即总“优数”个数减去左子区间里小于等于x的“优数”个数。

再考虑如何维护信息。\(max\)容易维护。\(ans_o=ans_{lson}+q(rson, max_{lson})\)即可。

最终的答案就是\(q(root, 0)\)。

Code

#include <algorithm>
#include <cstdio>
const int N = 100050;
typedef long long LL;
struct Frac{int x, y;Frac(int x = 1, int y = 0) : x(x), y(y) {}bool operator<(const Frac &f) const {return (LL)y * f.x < (LL)f.y * x;}
}maxv[N * 4];
int lenv[N * 4], Y[N];
int query(int o, int l, int r, Frac x) {if (!(x < maxv[o])) return 0;if (l == r) return 1;int mid = (l + r) / 2;return maxv[o << 1] < x? query(o << 1 | 1, mid + 1, r, x): query(o << 1, l, mid, x) + lenv[o] - lenv[o << 1];
}
void upd(int o, int l, int r) {if (l == r) {lenv[o] = 1;maxv[o] = Frac(l, Y[l]);} else {int lc = o << 1, rc = o << 1 | 1, mid = (l + r) / 2;maxv[o] = std::max(maxv[lc], maxv[rc]);lenv[o] = lenv[lc] + query(rc, mid + 1, r, maxv[lc]);}
}
void modify(int o, int l, int r, int x, int y) {if (l > x || r < x) return;if (l == r)Y[x] = y;else {int mid = (l + r) / 2;modify(o << 1, l, mid, x, y);modify(o << 1 | 1, mid + 1, r, x, y);}upd(o, l, r);
}
void build(int o, int l, int r) {maxv[o] = Frac(l, 0); lenv[o] = 1;if (l != r) {int mid = (l + r) / 2;build(o << 1, l, mid);build(o << 1 | 1, mid + 1, r);}
}
int main() {int n, m, x, y;scanf("%d%d", &n, &m);build(1, 1, n);while (m--) {scanf("%d%d", &x, &y);modify(1, 1, n, x, y);printf("%d\n", query(1, 1, n, Frac()));}return 0;
}

转载于:https://www.cnblogs.com/y-clever/p/8513175.html

BZOJ2957 楼房重建相关推荐

  1. [BZOJ2957]楼房重建

    楼房重建 题解 很容易发现,一个楼房能够被看到当且仅当它前面的楼房的斜率都比它的小. 我们显然可以把斜率这东西离散化下来,当成一个权值,所以我们相当于要事实维护有多少个不同的前缀最大值. 首先这应该很 ...

  2. BZOJ2957:楼房重建(线段树)

    Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些 ...

  3. BZOJ2957楼房重建

    传送门  https://www.luogu.org/problemnew/show/P4198 蒟蒻渣渣禹看到这个题时十分不想写线段树emmmm 于是乎....分块!!! 分块.思路就是:如果一个楼 ...

  4. Bzoj2957: 楼房重建

    题目 传送门 Sol 线段树,维护斜率单增的最高点和长度 更新,以下的都是指斜率 当前点的左儿子更新上来,右儿子递归 如果右儿子的左儿子的最大值大于左儿子的 加上算出右儿子的右儿子的贡献(右儿子贡献减 ...

  5. bzoj-2957 楼房重建

    题意: 数轴上有n个楼,分别在1~n这些点上: m次查询.每次改变一个楼的高度,问从(0,0)这个点能够看到多少楼: 题解: 对于一个楼来说要想看到这个楼.那么前面的楼的斜率一定比这个楼小: 那么考虑 ...

  6. BZOJ 2957楼房重建

    传送门 线段树 //Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include< ...

  7. P4198 楼房重建 线段树 + 区间合并

    传送门 文章目录 题意: 思路: 题意: 题面有点问题,按照人类正常的理解来就好啦. 思路: 可以想到维护每个位置的一个斜率,模拟的话就是从第一个位置开始向后选,当某个位置斜率大于当前位置的时候,答案 ...

  8. LG P4198 楼房重建(线段树)

    LG P4198 楼房重建 Solution 基础的线段树题,虽然我还不熟练就是了. 大概就是单点修改,求全局的极大子序列. 我们需要维护一个区间最大值aaa和极大子序列长度sss. 合并xxx的左右 ...

  9. [luogu P4198] 楼房重建(线段树 + 思维)

    luogu 楼房重建 problem solution code problem 洛谷链接 solution 非常巧妙的一道题,对线段树的运用很灵活. 显然这个与原点的连线可以想到将每个点转化为与原点 ...

最新文章

  1. Docker的安装和使用及其Docker容器间通信,云计算技术与应用实验报告
  2. Linux下使用命令生成二维码
  3. RabbitMQ简单介绍+Windows环境安装
  4. 微课|中学生可以这样学Python(例5.6、例5.7):集合应用
  5. 从QQ空间热度分析看社区营销
  6. 诺基亚指控联想侵权;格力回应“被中国移动取消中标资格”;微软暂停更新 Edge 浏览器 | 极客头条...
  7. CISA《网络安全事件和漏洞响应手册》提到的SSVC是什么?
  8. .NET Core 中读取appsettings.json配置文件的方法
  9. 如何学习UG编程?零基础入门学UG难吗
  10. oeasy教您玩转vim - 2 - # 使用帮助
  11. java 水晶按钮_java渲染水晶按钮
  12. 安卓手机云控系统框架源码,PHP+Autojs, ,这套是空框架源码
  13. 电脑怎么设置时间自动关机?
  14. xp此计算机无法连接到,XP系统无法连接到网络怎么办
  15. 从钉钉后台API获取企业通信录
  16. LabVIEW笔记(一)
  17. Oracle SQL前三行,后三行
  18. python实现txt转word
  19. 用Adobe Reader PDF阅读器来验证电子签名有效性
  20. c语言程序设计教程中国农业出版社答案,C语言程序设计教程杨路明课后习题答案北京邮电大学出版社.pdf...

热门文章

  1. 统计一个长度为2的子字符串在另一个字符串中出现的次数.例如:假定输入的字符串为“asd asasdfg asd as zx67 asd mklo”,子字符串为“as”,函数返回值为6。
  2. python核心编程第三版_《Python核心编程(第3版)》
  3. Java企业面试算法新得体会之5字符串问题24问
  4. Java消息中间件--ActiveMq,RabbitMQ,Kafka
  5. mysql主从复制 读写分离
  6. Bootstrap研究3-基础html元素
  7. 清结算内部勾兑业务一个比较有意思的问题整理
  8. pytorch中的gather函数_Pytorch中Emdedding函数的解释及使用方法
  9. Go面试题 | []int 能转换为 []interface 吗?
  10. Rand7()实现Rand10()