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 ...
随机推荐
- Python使用教程
1.下载python windows:http://www.python.org/download/ 2.环境变量: 3.pycharm下载:http://www.python.org/downloa ...
- 剑指offer-第六章面试中的各项能力(翻转单词的顺序VS左旋转字符串)
//题目1:翻转单词顺序例如“Hello world!”翻转后为world! Hello. //思路:首先翻转整个字符串,然后再分别翻转每个单词. //题目2:左旋转字符串,是将字符串的前面几个(n) ...
- 【java规则引擎】一个基于drools规则引擎实现的数学计算例子
最近在研究JBPM工作流引擎,发现JBPM是基于Drools的,官方文档查看得知Drools是一款规则引擎.兴趣之下,仔细了解了下 Drools,Drools作为JBoss出品的一款开源推理和规则引擎 ...
- fn project AWS Lambda 格式 functions
Creating Lambda Functions Creating Lambda functions is not much different than using regular funct ...
- maven搭建
http://blog.csdn.net/zhshulin/article/details/30779873 http://blog.csdn.net/zhshulin/article/details ...
- MySQL连接查询、联合查询、子查询
参考地址:http://blog.csdn.net/u011277123/article/details/54863371 1.MySQL连接查询 连接查询:将多张表(>=2)进行记录的连接(按 ...
- Linux安装微信
地址:http://www.toutiao.com/i6362126617556288001/#6649976-tsina-1-90079-4471e2b057b5019ad452c722f04bba ...
- keepalived 预防脑裂检测脚本
1 检查vip [root@mysql2 keepalived]# cat /etc/keepalived/check_brain_keepalived.sh #!/bin/bash # 检查脑裂的脚 ...
- StarkSoft题库管理系统
一.功能介绍 1.自定义试题库管理系统目录.难易程度,题型,知识库等. 2.试题录入. 3.强大的试题编辑功能,并与通常应用编辑工具有共通. 4.灵活的试卷构造功能,用户可自定 ...
- oracle显示数据库名和表名
oracle查看表名 select table_name from user_tables; select table_name from dba_tables; select * from all_ ...