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栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些 ...
随机推荐
- 线上分享-- 基于DDD的.NET开发框架-ABP介绍
前言 为了能够帮助.Net开发者开拓视野,更好的把最新的技术应用到工作中,我在3月底受邀到如鹏网.net训练营直播间为各位学弟学妹们进行ABP框架的直播分享.同时为了让更多的.NET开发者了解ABP框 ...
- linux下expect环境安装以及简单脚本测试
expect是交互性很强的脚本语言,可以帮助运维人员实现批量管理成千上百台服务器操作,是一款很实用的批量部署工具!expect依赖于tcl,而linux系统里一般不自带安装tcl,所以需要手动安装 下 ...
- CF367C. Hard problem
链接[http://codeforces.com/group/1EzrFFyOc0/contest/706/problem/C] 题意: 他希望它们按词典顺序排序(就像字典中那样),但他不允许交换其中 ...
- swap函数
#include<iostream> using namespace std; void swap(int& a,int& b){ int t=a; a=b; b=t; } ...
- Week 1 工程文档
计算器——工程文档 一.输入与格式 1.数据规模 本文档的输入基于如下的要求: (1)既然是小学生,我们假设他们不会计算超过10亿的数字. (2)既然是出考试题,那么也不会出超过10亿道题目. 也就是 ...
- <<浪潮之巅>>阅读笔记二
好的文章总是慢慢吸引着你去阅读,这本书的作者是吴军博士,让我很钦佩的是他还是一个很著名的程序员.其实我感觉理科生在写作方面的能力是很欠缺的,我们经常做到了有观点,但是做不到和别人表达清楚你的观点想法, ...
- There are no enabled repos.
今天要记录一下自己懵逼的一天,原来自己是Ubuntu系统,还以为是centos,导致命令错了 There are no enabled repos. Run "yum repolist al ...
- 开始第一段SPRINT
四则运算Sprint计划 1.小组成员: 李豌湄:master 江丹仪:产品负责人 2.现状: 初步有一个四则运算的程序代码, 我们这个团队的编程基础比较薄弱,还不知道怎么将程序与数据库连接,也是在边 ...
- CSS字体大小之em,px,百分比
首先要记住网页中常规字体的大小为16px. px是用来设置字体的绝对大小.通常为用于物理值的设置.我们在互联网上看到的常规字体大小为16px.而em是指相对于父元素的大小.1em是父元素的1倍,2em ...
- SpringMVC 网站
https://mp.weixin.qq.com/s/MLCIcQcevLBpZFOQce3DMQ