洛谷 P4198 楼房重建
思路
此题可转化为以下模型
给定序列\(a[1...n]\),支持单点修改,每次求区间单调栈大小
\(n,Q\le 10^5\)
区间单调栈是什么呢?对于一个区间,建立一个栈,首先将第一个元素入栈,从左往右扫,如果当前元素大于等于栈顶元素,就将其入栈,由此形成的栈即为单调不减的区间单调栈。
转化一下,其实就是求区间内满足\(a[i]=\max\limits_{j=1}^ia[j]\)的\(a[i]\)的个数。
一个自然的想法是维护单调栈的大小\(siz\),那么如何去进行区间的合并呢?
合并两个子区间时,假设左子区间为\(L\),右子区间为\(R\),考虑合并之后的单调栈的组成部分:
第一部分:\(L\)的单调栈
因为单调栈是从左往右做的,所以\(L\)的单调栈必然是大区间单调栈的一部分
剩余部分
设出函数\(calc(now,pre)\),\(now\)表示当前节点,\(pre\)表示当前单调栈的栈顶,\(calc\)函数计算剩余部分的单调栈的大小
总的单调栈大小\(siz\)就是\(L_{siz}+calc(R,L_{max})\)
calc的实现
现在有\(calc(now,pre)\),\(l\)表示\(now\)的左子树,\(r\)表示\(now\)的右子树
- 如果\(pre>l_{max}\),说明整个左子区间都不用考虑了,此时答案就变成了\(calc(r,pre)\)
- 如果\(pre\le l_{max}\),此时\(l\)是有贡献的,他对\(siz\)的贡献就是\(calc(l,pre)\),右子树的贡献为\(calc(r,l_{max})\),总贡献就是\(calc(l,pre)+calc(r,l_{max})\)
至此\(calc\)就推完了,但是我们发现如果仅仅是这样的话,在最坏的情况下,复杂度会爆炸,那么怎么优化呢?
观察\(calc(r,l_{max})\),发现它就等于\(siz-l_{siz}\),所以第二种情况就可以变成\(calc(l,pre)+siz-l_{siz}\),其中\(siz\)都是可以处理好的
这样我们就可以在\(O(\log n)\)的时间里完成一次合并
总时间复杂度\(O(Q\log^2 n)\)
代码
/*
Author:loceaner
*/
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lson rt << 1
#define rson rt << 1 | 1
using namespace std;
const int A = 1e5 + 11;
const int B = 1e6 + 11;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
inline int read() {
char c = getchar();
int x = 0, f = 1;
for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}
double val;
int n, m, ans, pos;
struct node { double maxn; int siz; } a[A << 2];
void build(int rt, int l, int r) {
if (l == r) return;
int mid = (l + r) >> 1;
build(lson, l, mid), build(rson, mid + 1, r);
}
inline int calc(int rt, int l, int r, double h) {
if (l == r) return a[rt].maxn > h;
int mid = (l + r) >> 1;
if (a[lson].maxn <= h) return calc(rson, mid + 1, r, h);
return calc(lson, l, mid, h) + a[rt].siz - a[lson].siz;
}
inline void update(int rt, int l, int r) {
if (l == r) {
a[rt].maxn = val, a[rt].siz = 1;
return;
}
int mid = (l + r) >> 1;
if (pos <= mid) update(lson, l, mid);
else update(rson, mid + 1, r);
a[rt].maxn = max(a[lson].maxn, a[rson].maxn);
a[rt].siz = a[lson].siz + calc(rson, mid + 1, r, a[lson].maxn);
}
int main() {
n = read(), m = read();
build(1, 1, n);
while (m--) {
int x = read(), y = read();
pos = x, val = (double) y / x;
update(1, 1, n);
cout << a[1].siz << '\n';
}
}
洛谷 P4198 楼房重建的更多相关文章
- 洛谷P4198 楼房重建 (分块)
洛谷P4198 楼房重建 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题, ...
- 洛谷 P4198 楼房重建 题解
题面 首先你要知道题问的是什么:使用一种数据结构,动态地维护以1为起点地最长上升子序列(把楼房的高度转化成斜率地序列)的长度: 怎么做?线段树! 我们在线段树上维护两个东西:1.这个区间内斜率的最大值 ...
- 洛谷P4198 楼房重建 单调栈+线段树
正解:单调栈+线段树 解题报告: 传送门! 首先考虑不修改的话就是个单调栈板子题昂,这个就是 然后这题的话,,,我怎么记得之前考试好像有次考到了类似的题目昂,,,?反正我总觉着这方法似曾相识的样子,, ...
- 洛谷P4198 楼房重建(线段树)
题意 题目链接 Sol 别问我为什么发两遍 就是为了骗访问量 这个题的线段树做法,,妙的很 首先一个显然的结论:位置\(i\)能被看到当且仅当\(\frac{H_k}{k} < \frac{H_ ...
- 洛谷P4198 楼房重建
题意:给定序列,每次修改一个值,求前缀最大值的个数. 解:线段树经典应用. 每个节点维护最大值和该区间前缀最大值个数. 发现我们不用下传标记,只需要合并区间. 需要实现一个函数int ask([l r ...
- 洛谷 P4198 楼房重建 线段树维护单调栈
P4198 楼房重建 题目链接 https://www.luogu.org/problemnew/show/P4198 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上 ...
- P4198 楼房重建
P4198 楼房重建 集中写博客= = 首先把高度变成斜率 然后就比较玄学了,首先用线段树维护一个区间的斜率最大值,和只看这个区间时能看见的楼房个数ans 然后更新时先更新max,再处理神奇的ans ...
- 洛谷P1119-灾后重建-floyd算法
洛谷P1119-灾后重建 题目描述 给出\(B\)地区的村庄数NN,村庄编号从\(0\)到\(N-1\),和所有\(M\)条公路的长度,公路是双向的. 给出第\(i\)个村庄重建完成的时间\(t_i\ ...
- 洛谷 P3905 道路重建
题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现在有两个重要城市A和B ...
随机推荐
- Mysql and ORM
本节内容 数据库介绍 mysql 数据库安装使用 mysql管理 mysql 数据类型 常用mysql命令 创建数据库 外键 增删改查表 权限 事务 索引 python 操作mysql ORM sql ...
- JavaWeb项目的目录结构解释(上):
当我们在IDEA创建JavaWeb项目时,默认的一般会有下图的目录结构,你的开发就是按照下列结构进行开发的,那么我就逐一解释他们的意思: 首先是demo:这个是项目的名字,一般你是自己创建一个与自己项 ...
- JVM系列6-GC算法
一.如何判定垃圾? 1.1.Reference Count引用计数法:引用计数count=0的对象 1.2.Root Seaching根可达法:从root开始不可达的对象 常见的可做GC roots的 ...
- 集训作业 洛谷P1032 字串变换
集训的题目有点多,先写困难的绿题吧(简单的应该想想就会了) 嗯,这个题看起来像个搜索呢(就是个搜索) 我们仔细想想就知道这个题肯定不能用深搜,可以优化的地方太少了,TLE是必然的. 那我们该怎么办呢? ...
- CUDA中关于C++特性的限制
CUDA中关于C++特性的限制 CUDA官方文档中对C++语言的支持和限制,懒得每次看英文文档,自己尝试翻译一下(没有放lambda表达式的相关内容,太过于复杂,我选择不用).官方文档https:// ...
- Maven配置文件中的版本使用-SNAPSHOT
SNAPSHOT是什么? SNAPSHOT是快照,是一种特殊的版本,制定了某个当前的开发进度副本.不同于正式版本,Maven每次构建都会在远程仓库中检查新的快照.如此每次发布更新代码的快照到仓库中,新 ...
- 盘点 6 个被淘汰的 Java 技术,它们都曾经风光过!
大家好啊,今天栈长给大家分享下我的开发历程中,我知道的那些被淘汰的技术或者框架,有些我甚至都没有用过,但我知道它曾经风光过. 废话不多说,下面我要开始吹了-- 1.Swing 下面这个是用 swing ...
- jmeter零散知识点
- Python语言及其应用|PDF高清完整版免费下载|百度云盘|Python
百度云盘:Python语言及其应用PDF高清完整版免费下载 提取码:6or6 内容简介 本书介绍Python 语言的基础知识及其在各个领域的具体应用,基于最新版本3.x.书中首先介绍了Python 语 ...
- vj map
/* * 换行好烦人呀! */ #include <iostream> #include <map> #include <string> using namespa ...