P4198 楼房重建
P4198 楼房重建
一道优秀线段树题
题目大意,有1至n个位置,每个位置有一个楼房,初始高度为0,高度为的楼房可以抽象成端点为的线段
你站在,看到一栋楼的前提是与的连线不与任何线段相交
每次修改一栋楼的高度,问你能看到的楼房有多少
首先考虑求出与的连线的斜率,题目求满足的i的个数,考虑线段树维护区间的最高点,和其的个数
然后发现对于两个区间合并,对于题意,左区间一定会选,所以就维护一个询问,在一个区间,有最小高度限定的
的个数
然后发现对于左区间,若最大值大于lim,则右区间一定满足,只用递归左区间
如果最大值小于等于lim,则左区间无贡献,只用递归右区间
然后就可以解决本题
#include<bits/stdc++.h>
using namespace std;
int n,m,a[100005];
struct node{
int l;
double h;
}t[100005<<2];
int ask(int o,int l,int r,double lim){
if(l==r){
if(t[o].h>lim) return 1;
else return 0;
}int mid=l+r>>1;
if(t[o].h<=lim) return 0;
if(t[o*2].h>lim) return t[o].l-t[o*2].l+ask(o*2,l,mid,lim);
else return ask(o*2+1,mid+1,r,lim);
}
void change(int o,int l,int r,int x,double height){
if(l==r){
t[o]={1,height};
return ;
}int mid=l+r>>1;
if(mid>=x) change(o*2,l,mid,x,height);
else change(o*2+1,mid+1,r,x,height);
t[o].h=max(t[o*2].h,t[o*2+1].h),t[o].l=t[o*2].l+ask(o*2+1,mid+1,r,t[o*2].h);
}
int main(){
scanf("%d%d",&n,&m);
while(m--){
int w,h;
scanf("%d%d",&w,&h);
change(1,1,n,w,1.0*h/w);
printf("%d\n",t[1].l);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通