luogu P4198 楼房重建——线段树
题目大意:
小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 楼房重建——线段树的更多相关文章
- [Luogu P4198]楼房重建(线段树)
题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些事件发生在一个 ...
- 洛谷P4198 楼房重建(线段树)
题意 题目链接 Sol 别问我为什么发两遍 就是为了骗访问量 这个题的线段树做法,,妙的很 首先一个显然的结论:位置\(i\)能被看到当且仅当\(\frac{H_k}{k} < \frac{H_ ...
- 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$,然后块内二 ...
- luogu题解P4198楼房重建--线段树神操作
题目链接 https://www.luogu.org/problemnew/show/P4198 分析 一句话题意,一条数轴上有若干楼房,坐标为\(xi\)的楼房有高度\(hi\),那么它的斜率为\( ...
- [BZOJ29957] 楼房重建 - 线段树
2957: 楼房重建 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 3294 Solved: 1554[Submit][Status][Discus ...
- bzoj 2957: 楼房重建 线段树
2957: 楼房重建 Time Limit: 10 Sec Memory Limit: 256 MB[Submit][Status][Discuss] Description 小A的楼房外有一大片施 ...
- 【题解】Luogu P4198 楼房重建
原题传送门 根据斜率来建线段树,线段树维护区间最大斜率以及区间内能看见的楼房的数量(不考虑其他地方的原因,两个节点合并时再考虑) 细节见程序 #include <bits/stdc++.h> ...
- bzoj 2957: 楼房重建 ——线段树
Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些 ...
随机推荐
- Libp2p学习(一)
Libp2p学习 参考资料:libp2p-specifications : https://github.com/libp2p/specs 持续更新ing 1. 介绍 Libp2p的实现目标是: 支持 ...
- linux-IO重定向-文本流重定向
输出重定向的追加和覆盖 标准输出就这两种: 覆盖和追加 >> 是重定向操作符 1 是 命令的文件描述符 重定向操作符合文件描述符之间不能存在空白符 否则1会被当做是文件被读取 将正确和错误 ...
- 饿了么element UI<el-dialog>弹出层</el-dialog>修改默认样式不能在<style scoped>修改
如果在非scoped下,修改el-dialog自动添加的DIV类名的style加上important,可以覆盖原来的width,但这样会让整个项目的样式都乱套. 如果在scoped下修改style.所 ...
- 个人阅读作业 final
前两次阅读作业链接: http://www.cnblogs.com/SteelPillar/p/4027877.html http://www.cnblogs.com/SteelPillar/p/40 ...
- Scrum Meeting NO.8
Scrum Meeting No.8 1.会议内容 2.任务清单 徐越 序号 近期的任务 进行中 已完成 1 代码重构:前端通讯模块改为HttpClient+Json √ 2 添加对cookies的支 ...
- 《linux内核设计与实现》第十八章
第十八章 调试 调试工作艰难是内核级开发区别于用户级开发的一个显著特点. 一.准备开始 1.内和调试需要什么 一个bug(大部分bug通常都不是行为可靠而且定义明确的) 一个藏匿bug的内核版本(知道 ...
- squid反向代理
反向代理的作用是就爱那个网站中的静态自原本地化.也就是将一部分本应该有原是服务器处理的请求交给 Squid 缓存服务处理 编辑 Squid 服务程序的配置文件*(正向代理与反向代理不能同时使用,) ...
- suqid透明正向代理
如果想实现透明正向代理,则必需将用户的网关IP指向 Squid 服务器,而此后便无需再修改浏览器选项 在命令行 <菜单+R> 中使用 ping 命令: ping www.baidu.c ...
- PAT 1002 写出这个数
https://pintia.cn/problem-sets/994805260223102976/problems/994805324509200384 读入一个自然数n,计算其各位数字之和,用汉语 ...
- mybatis集成redis
系统原生集成的Ehcache, 但是监控需要(version 2.7),Ehcache Monitor http://www.ehcache.org/documentation/2.7/operati ...