题目大意:

小A在平面上(0,0)点的位置,第i栋楼房可以用一条连接(i,0)和(i,Hi)的线段表示,其中Hi为第i栋楼房的高度。如果这栋楼房上任何一个高度大于0的点与(0,0)的连线没有与之前的线段相交,那么这栋楼房就被认为是可见的。

施工队的建造总共进行了M天。初始时,所有楼房都还没有开始建造,它们的高度均为0。在第i天,建筑队将会将横坐标为Xi的房屋的高度变为Yi(高度可以比原来大—修建,也可以比原来小—拆除,甚至可以保持不变—建筑队这天什么事也没做)。请你帮小A数数每天在建筑队完工之后,他能看到多少栋楼房?

分析:

显然可以想到进行斜率处理,通过斜率的单调递增来求出len。

其实答案就是整个1—n区间中从第一项开始,每一个大于前一项的必选,小于等于前一项的必须不选,所的得到的序列长度。

因为区间是固定的,并且发现一个区间内的答案可以通过两个子区间用某种方式进行转移。所以可以考虑到线段树做法。

线段树中只需要维护两个值,一个是区间最大值,还有一个是区间序列长度(按照刚才的理解)的值。

建树(甚至不用),修改,甚至不用pushdown,一切好说。但是发现pushup不好处理,显然两个子区间的值不能直接合并。必须满足一定关系。

可以发现,区间内的第一项一定在这个序列内,区间最大值也一定在这个序列内。

对于要被pushup的区间,它的两个子区间已经处理好了,容易知道,左儿子区间内的序列每一项一定都在这个大区间内。(因为前面形态固定,又不能选择不看到)所以只需要处理右儿子区间和左儿子区间最大值的关系,即可递归处理len值。

递归要传入该区间的值必须大于的最小值,设为lx。对于开始进入时,也就是左儿子的最大值。

1.如果l==r,该位置的值大于lx,return1,否则return0;

2.将该区间劈成两段,设为s1,s2区间。

①如果s1的最大值小于等于lx,那么s1必然不会对答案产生贡献,去找s2。即代码中: return pushup2(lx,s2,mid+1,r)

②如果s1的最大值大于lx,那么s2中剩下的在s1,s2组成的原区间中做贡献的项一定能贡献到最终答案中。即+l(x)-l(s1),这里注意,不是 l(s2),因为可能在l(s2)中存在的项,不一定在l(x)这个大区间中出现。所以这两个值是完全不同的概念。

之后再去寻找s1. 即:return pushup2(lx,s1,l,mid)+l(x)-l(s1);

核心代码:

int pushup2(double lx,int x,int l,int r)
{
if(m(x)<=lx) return ;//剪枝
if(a[l]>lx) return l(x);//剪枝
if(l==r) return a[l]>lx;//①
int s1=x<<,s2=x<<|;
int mid=(l+r)>>;
if(m(s1)<=lx) return pushup2(lx,s2,mid+,r);//②
else return pushup2(lx,s1,l,mid)+l(x)-l(s1);//③
}

详见代码:

#include<bits/stdc++.h>
using namespace std;
const int N=+;
int n,m;
double a[N];
struct node{
double mx;
int len;
#define m(x) t[x].mx
#define l(x) t[x].len
}t[*N];
void pushup1(int x)
{
m(x)=max(m(x<<),m(x<<|));
}
int pushup2(double lx,int x,int l,int r)
{
if(m(x)<=lx) return ;
if(a[l]>lx) return l(x);
if(l==r) return a[l]>lx;
int s1=x<<,s2=x<<|;
int mid=(l+r)>>;
if(m(s1)<=lx) return pushup2(lx,s2,mid+,r);
else return pushup2(lx,s1,l,mid)+l(x)-l(s1);
}
void chan(int x,int l,int r,int to,int c)
{
if(l==r&&l==to)
{
m(x)=(double)c/to;
l(x)=;
return ;
}
int mid=(l+r)>>;
if(to<=mid) chan(x<<,l,mid,to,c);
else if(to>mid) chan(x<<|,mid+,r,to,c);
pushup1(x);
l(x)=l(x<<)+pushup2(m(x<<),x<<|,mid+,r);
}
int main()
{
scanf("%d%d",&n,&m);
int x,y;
for(int i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
a[x]=(double)y/x;
chan(,,n,x,y);
printf("%d\n",t[].len);
}
return ;
}

总结:

1.其实这个题就是把pushup logn化,是pushup一种难度升级版。

2.只要可以想办法区间合并的问题,都可以尝试用线段树解决。虽然有时候一看看不出来。

luogu P4198 楼房重建——线段树的更多相关文章

  1. [Luogu P4198]楼房重建(线段树)

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

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

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

  3. Luogu P4198 楼房重建 (李超线段树)

    题目 传送门 题解 首先转化成到(0,0)(0,0)(0,0)的斜率. 那么就是求多少个点是前缀最大值. 做法是线段树,用gao(i,x)gao(i,x)gao(i,x)表示在iii区间内,之前最大值 ...

  4. Luogu P4198 楼房重建 分块 or 线段树

    思路:分块 提交:2次(第一次的求解有问题) 题解: 设块长为$T$,我们开$N/T$个单调栈,维护每一块的上升斜率. 修改时暴力重构整个块,$O(T)$ 求解时记录一个最大斜率$lst$,然后块内二 ...

  5. luogu题解P4198楼房重建--线段树神操作

    题目链接 https://www.luogu.org/problemnew/show/P4198 分析 一句话题意,一条数轴上有若干楼房,坐标为\(xi\)的楼房有高度\(hi\),那么它的斜率为\( ...

  6. [BZOJ29957] 楼房重建 - 线段树

    2957: 楼房重建 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 3294  Solved: 1554[Submit][Status][Discus ...

  7. bzoj 2957: 楼房重建 线段树

    2957: 楼房重建 Time Limit: 10 Sec  Memory Limit: 256 MB[Submit][Status][Discuss] Description 小A的楼房外有一大片施 ...

  8. 【题解】Luogu P4198 楼房重建

    原题传送门 根据斜率来建线段树,线段树维护区间最大斜率以及区间内能看见的楼房的数量(不考虑其他地方的原因,两个节点合并时再考虑) 细节见程序 #include <bits/stdc++.h> ...

  9. bzoj 2957: 楼房重建 ——线段树

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

随机推荐

  1. 身在上海的她,该不该继续"坚持"前端开发?

    作者:13 GitHub:https://github.com/ZHENFENG13 版权声明:本文为原创文章,未经允许不得转载. 一 对于目前的IT行业,我实在不想她还没在这个行业中站稳脚跟就开始有 ...

  2. MFS+Keepalived双机高可用热备方案操作记录

    基于MFS的单点及手动备份的缺陷,考虑将其与Keepalived相结合以提高可用性.在Centos下MooseFS(MFS)分布式存储共享环境部署记录这篇文档部署环境的基础上,只需要做如下改动: 1) ...

  3. 《linux内核设计与实现》第三章

    1.进程 进程就是正在执行的程序代码的实时结果,不仅包含可执行代码,还包括其他资源,比如:打开的文件,挂起的信号,内核内部数据结构,处理器状态,一个或多个具有内存映射的内存地址空间及一个或多个执行线程 ...

  4. 基于Spring3 MVC实现基于form表单文件上传

    http://blog.csdn.net/jia20003/article/details/8474374/

  5. Java 类的加载

    package com.cwcec.p2; class C { public static final int SIZE; static { SIZE = 100; System.out.printl ...

  6. 软件工程-pair work[附加题]

    首先,在分组之前,我和室友周敏轩已经详细阅读了往届学长的博客,认为电梯调度这个项目应该先做UI会比较好一点,于是动手展开了UI的编写;但分组结果并没有如我们所愿,但我们依然共同进行了UI的编写,希望在 ...

  7. [系统软件]Ubuntu 18.04中的Shutter禁用了“编辑”选项解决

    本文引用自linux公社, 原文请点击 : https://www.linuxidc.com/Linux/2018-04/151911.htm   在Ubuntu 18.04中安装了我最喜欢的截图工具 ...

  8. 自己写的browse.bat与perl写的url_handler.pl的比较

    以前自己也写过Windows下自动打开多个浏览器测试某个URI,提高浏览器兼容性测试效率. 但是写的browse.bat文件还是最基础简陋的 @echo off if '%1'=='-c' ( sta ...

  9. Docker(十五)-Docker的数据管理(volume/bind mount/tmpfs)

    Docker提供了三种不同的方式用于将宿主的数据挂载到容器中:volumes,bind mounts,tmpfs volumes.当你不知道该选择哪种方式时,记住,volumes总是正确的选择. vo ...

  10. [转帖]Linux内核为大规模支持100Gb/s网卡准备好了吗?并没有

    Linux内核为大规模支持100Gb/s网卡准备好了吗?并没有 之前用 千兆的机器 下载速度 一般只能到 50MB 左右 没法更高 万兆的话 可能也就是 200MB左右的速度 很难更高 不知道后续的服 ...