思路

此题可转化为以下模型

给定序列\(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 楼房重建的更多相关文章

  1. 洛谷P4198 楼房重建 (分块)

    洛谷P4198 楼房重建 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题, ...

  2. 洛谷 P4198 楼房重建 题解

    题面 首先你要知道题问的是什么:使用一种数据结构,动态地维护以1为起点地最长上升子序列(把楼房的高度转化成斜率地序列)的长度: 怎么做?线段树! 我们在线段树上维护两个东西:1.这个区间内斜率的最大值 ...

  3. 洛谷P4198 楼房重建 单调栈+线段树

    正解:单调栈+线段树 解题报告: 传送门! 首先考虑不修改的话就是个单调栈板子题昂,这个就是 然后这题的话,,,我怎么记得之前考试好像有次考到了类似的题目昂,,,?反正我总觉着这方法似曾相识的样子,, ...

  4. 洛谷P4198 楼房重建(线段树)

    题意 题目链接 Sol 别问我为什么发两遍 就是为了骗访问量 这个题的线段树做法,,妙的很 首先一个显然的结论:位置\(i\)能被看到当且仅当\(\frac{H_k}{k} < \frac{H_ ...

  5. 洛谷P4198 楼房重建

    题意:给定序列,每次修改一个值,求前缀最大值的个数. 解:线段树经典应用. 每个节点维护最大值和该区间前缀最大值个数. 发现我们不用下传标记,只需要合并区间. 需要实现一个函数int ask([l r ...

  6. 洛谷 P4198 楼房重建 线段树维护单调栈

    P4198 楼房重建 题目链接 https://www.luogu.org/problemnew/show/P4198 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上 ...

  7. P4198 楼房重建

    P4198 楼房重建 集中写博客= = 首先把高度变成斜率 然后就比较玄学了,首先用线段树维护一个区间的斜率最大值,和只看这个区间时能看见的楼房个数ans 然后更新时先更新max,再处理神奇的ans ...

  8. 洛谷P1119-灾后重建-floyd算法

    洛谷P1119-灾后重建 题目描述 给出\(B\)地区的村庄数NN,村庄编号从\(0\)到\(N-1\),和所有\(M\)条公路的长度,公路是双向的. 给出第\(i\)个村庄重建完成的时间\(t_i\ ...

  9. 洛谷 P3905 道路重建

    题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现在有两个重要城市A和B ...

随机推荐

  1. 为什么阿里、头条、美团这些互联网大厂都在用Spring Boot?

    前言 自 2014 年发布至今,Spring Boot 的搜索指数 一路飙升.没错 Spring Boot 越来越火了,作为一名行走一线的 Java 程序员,你可能在各个方面感受到了 Spring B ...

  2. CSS定位布局

    CSS定位布局 基础知识 在CSS布局中,定位布局也是一种非常常见的技术手段,我们以京东为例: 上面是非常好的例子,对于定位布局来说它可以将一个元素放在页面上的任意一个位置. 但是定位布局也不能滥用, ...

  3. 区间dp复习 之 tyvj 1198 矩阵连乘

    题目描述 一个\(n*m\)矩阵由\(n\)行\(m\)列共\(n*m\)个数排列而成.两个矩阵\(A\)和\(B\)可以相乘当且仅当\(A\)的列数等于\(B\)的行数.一个\(N*M\)的矩阵乘以 ...

  4. italic和oblique的区别

    italic和oblique都是向右倾斜的文字, 但区别在于Italic是指斜体字,而Oblique是倾斜的文字(让没有斜体属性的文字倾斜), 对于没有斜体的字体应该使用Oblique属性值来实现倾斜 ...

  5. 利用Serverless应用搭建Hexo博客

    本文将介绍如何使用火爆的Serverless应用,15分钟快速搭建Hexo博客.以腾讯云提供的Serverless应用–云开发为例: 步骤1:安装 CloudBase CLI 以及本地部署 Hexo ...

  6. 分布式锁(3) ----- 基于zookeeper的分布式锁

    分布式锁系列文章 分布式锁(1) ----- 介绍和基于数据库的分布式锁 分布式锁(2) ----- 基于redis的分布式锁 分布式锁(3) ----- 基于zookeeper的分布式锁 代码:ht ...

  7. ubuntu安装 jdk

    首先查一下当前JDK的版本 ,一般是系统自带Jdk$ java -version 然后根据版本8安装完整版的OpenJDK $ sudo apt-get install openjdk-8-jdk 如 ...

  8. 前端学习(十一):CSS性质

    进击のpython ***** 前端学习--CSS性质 那在CSS上还有一些很重要的性质:继承性,层叠性以及特殊性 那本小节就基于这三个性质进行展开... ... 继承性 在CSS的某些样式是具有继承 ...

  9. AList的具体实现 #CS61B-sp18-2.5

    实现一个Array based list,其功能包括获取长度size,添加元素至最后addLast,得到元素get和去除最后一个元素. 设计思路及其实现: 我们都知道在获取数据的时候,直接调用缓存里面 ...

  10. Day04_企业权限管理(SSM整合)

    学于黑马程序员和传智播客联合做的教学项目 感谢 黑马程序员官网 传智播客官网 个人根据教程的每天的工作进度的代码和资料 密码:cti5 b站在线视频 微信搜索"艺术行者",关注并回 ...