Luogu 4198 楼房重建
BZOJ 2957
挺妙的题。
先把题目中的要求转化为斜率,一个点$(x, y)$可以看成$\frac{y}{x}$,这样子我们要求的就变成了一个区间内一定包含第一个值的最长上升序列。
然后把这个序列开成线段树,维护一下区间内的答案$res$和最大值$mx$,显然对于叶子结点有$mx = a_l$,$res = 1$。
$mx$的更新非常简单直接取个最大值就好了,但是$res$的更新有一些复杂,对于一个区间$[l, r]$,左儿子$[l, mid]$的值可以直接加过来,因为左儿子一定会被选到,但是右儿子的值并不那么容易计算,我们用$solve(l, r, v)$表示区间$[l, r]$内第一个值超过$v$的元素必选的最长上升序列的大小,当$l == r$的时候,只要观察$mx$是否大于$v$就可以得到答案,而$solve$函数的合并则与左儿子区间的最大值有关,具体来说:当$mx_{lc} > v$的时候,右儿子全部被选到,然后递归计算左儿子$solve(l, mid, v)$,否则递归计算右儿子。
一次合并需要访问$log$个结点,总时间复杂度$O(nlog^2n)$。
Code:
#include <cstdio>
#include <cstring>
using namespace std;
typedef double db; const int N = 1e5 + ; int n, qn; inline void read(int &X) {
X = ; char ch = ; int op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline db max(db x, db y) {
return x > y ? x : y;
} namespace SegT {
int res[N << ];
db mx[N << ]; #define lc p << 1
#define rc p << 1 | 1
#define mid ((l + r) >> 1) int solve(int p, int l, int r, db v) {
if(l == r) return (mx[p] > v);
if(mx[lc] <= v) return solve(rc, mid + , r, v);
else return solve(lc, l, mid, v) + res[p] - res[lc];
} void modify(int p, int l, int r, int x, db v) {
if(l == r) {
mx[p] = v;
res[p] = ;
return;
} if(x <= mid) modify(lc, l, mid, x, v);
else modify(rc, mid + , r, x, v); mx[p] = max(mx[lc], mx[rc]);
res[p] = res[lc] + solve(rc, mid + , r, mx[lc]);
} } using namespace SegT; int main() {
read(n), read(qn);
for(int x, v; qn--; ) {
read(x), read(v);
modify(, , n, x, (db)v / x);
printf("%d\n", res[]);
}
return ;
}
Luogu 4198 楼房重建的更多相关文章
- 【题解】Luogu P4198 楼房重建
原题传送门 根据斜率来建线段树,线段树维护区间最大斜率以及区间内能看见的楼房的数量(不考虑其他地方的原因,两个节点合并时再考虑) 细节见程序 #include <bits/stdc++.h> ...
- luogu P4198 楼房重建——线段树
题目大意: 小A在平面上(0,0)点的位置,第i栋楼房可以用一条连接(i,0)和(i,Hi)的线段表示,其中Hi为第i栋楼房的高度.如果这栋楼房上任何一个高度大于0的点与(0,0)的连线没有与之前的线 ...
- [Luogu P4198]楼房重建(线段树)
题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些事件发生在一个 ...
- [Luogu] P4198 楼房重建
题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些事件发生在一个 ...
- Luogu P4198 楼房重建 (李超线段树)
题目 传送门 题解 首先转化成到(0,0)(0,0)(0,0)的斜率. 那么就是求多少个点是前缀最大值. 做法是线段树,用gao(i,x)gao(i,x)gao(i,x)表示在iii区间内,之前最大值 ...
- Luogu P4198 楼房重建 分块 or 线段树
思路:分块 提交:2次(第一次的求解有问题) 题解: 设块长为$T$,我们开$N/T$个单调栈,维护每一块的上升斜率. 修改时暴力重构整个块,$O(T)$ 求解时记录一个最大斜率$lst$,然后块内二 ...
- 洛谷 P4198 楼房重建 线段树维护单调栈
P4198 楼房重建 题目链接 https://www.luogu.org/problemnew/show/P4198 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上 ...
- bzoj 2957: 楼房重建 线段树
2957: 楼房重建 Time Limit: 10 Sec Memory Limit: 256 MB[Submit][Status][Discuss] Description 小A的楼房外有一大片施 ...
- P4198 楼房重建
P4198 楼房重建 集中写博客= = 首先把高度变成斜率 然后就比较玄学了,首先用线段树维护一个区间的斜率最大值,和只看这个区间时能看见的楼房个数ans 然后更新时先更新max,再处理神奇的ans ...
随机推荐
- 如何理解Robot Framework
不知不觉公众号已经有很多人关注了,小编先谢谢大家的支持-今天我们就来谈一谈我对RF的理解,因为前段时间换了工作,目前RF知识基本用不上了.其实我在上一份工作中大部分都是在反复的使用前面讲过的知识——其 ...
- 初识ADO.NET
摘要 作为.NET框架最重要的组件之一,ADO.NET扮演着应用程序与数据交互的重要的角色.本文将从宏观的角度来探讨ADO.NET,和大家一起了解ADO.NET来龙去脉以及ADO.NET的主要组成部分 ...
- 转载论文关于fir滤波器的fpga实现
摘 要 本文讨论的FIR滤波器因其具有严格的线性相位特性而得到广泛的应用.在工程实践中,往往要求信号处理具有实时性和灵活性,本论文研究FIR的FPGA解决方案正体现了电子系统的微型化和单片化. 本论文 ...
- python SQLAlchemy自动生成models文件
1.安装SQLAcodegen pip install sqlacodegen 2.执行 sqlacodegen mysql://root:123456@127.0.0.1:3306/test > ...
- FastAdmin 在线命令生成时出错的分析
FastAdmin 在线命令生成时出错的分析 出错现象 版本环境 FastAdmin 版本:1.0.0.20180806_beta 在线命令插件版本:1.0.3 分析 2018-08-13 16:12 ...
- Python学习系列(四)(列表及其函数)
Python学习系列(四)(列表及其函数) Python学习系列(一)(基础入门) Python学习系列(二)(基础知识) Python学习系列(三)(字符串) 一.基本概念 1,列表是什么? ...
- 第12篇 PSR-1规范
这个规范也不多,七点如下: 1. Overview Files MUST use only <?php and <?= tags. Files MUST use only UTF-8 wi ...
- Shell脚本基础知识详细介绍(一)
Shell本身是一个用C语言编写的程序,它是用户使用Linux的桥梁.Shell既是一种命令语言,又是一种程序设计语言.作为命令语言,它交互式地解释和执行用户输入的命令:作为程序设计语言,它定义了各种 ...
- java代码初学者适用,输入学生成绩,符合要求的过~~~~注意数据范围
总结:没有基础,我从点滴开始, package com.aaa; import java.util.Scanner; //输入“repate ”次数,输入学生成绩,低于60分,输出fail.否则输入p ...
- Linux学习笔记 -- 为 Shell 传递参数
我们可以在执行 Shell 脚本时,可以向脚本传递参数.脚本内获取参数的格式为:$n.(n 代表一个数字,0为所执行的shell脚本名称,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类 ...