[题解]luogu_P4198_楼房重建(线段树logn合并
Posted superminivan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解]luogu_P4198_楼房重建(线段树logn合并相关的知识,希望对你有一定的参考价值。
前言:最近购买了润滑脂和几个个性键帽,润滑脂用的太多大键稍微有点黏,但是我可以接受,钢丝声基本没有了,虽然没有拆下来卫星轴调试,但是效果还是有的,买了一个原厂高度的空格,好看是好看,用料也挺厚,但是形变非常严重,不过三十块要什么自行车,方向键是个手柄按键三角方块啥的透光键帽,用料也还行,但是字符有很明显的凹陷,看不出来但是摸起来就很明显,而且由于灯在轴的上方导致只有上面一半有光能透出来,但是我也不太在意
线段树update好题,首先把每个点转化为斜率,这样找一个递增序列即可,但是不同点在于这个递增序列不能挑,看到了就必须看到
这样怎么合并呢?首先对于一个区间左区间肯定全会看到,右区间如果全都矮于左区间最大值那肯定是看不到了,所以先记一个区间最大值,再记一个满足上面要求的区间上升序列长度,
如果右面有比左边大的怎么办呢?我们考虑右区间哪些会被看到,如果右区间的左区间最大值大于左区间的最大值,那么右区间的右区间一定可以全部看到,能看到的内容是右区间最长的合法序列在右区间的右区间的那部分,也就是len(x)-len(ls)
如果右区间的左区间最大值小于左区间的最大值,那么右区间的左区间一定不会被看到,只要去查右区间的右区间即可
#include<bits/stdc++.h> #define ls (x<<1) #define rs (x<<1|1) #define mid ((l+r)>>1) using namespace std; const int maxn=100009; int n,m; struct node int len; double mx; t[maxn<<2]; double a[maxn]; void upd(int x) t[x].mx=max(t[ls].mx,t[rs].mx); int find(int x,int l,int r,double lx) if(t[x].mx<=lx)return 0;//最大值小于查询的无贡献 if(l==r)return a[l]>lx;//叶子节点 if(a[l]>lx)return t[x].len;//最左端都大于了全部能看到 if(t[ls].mx>lx)return find(ls,l,mid,lx)+t[x].len-t[ls].len;//左区间能看到一部分那么t[x].len在右区间的那部分都能看到,递归查左区间 else return find(rs,mid+1,r,lx); void change(int x,int l,int r,int pos,int val) if(l==r) a[l]=t[x].mx=1.0*val/pos; t[x].len=1; return; if(pos<=mid)change(ls,l,mid,pos,val); else change(rs,mid+1,r,pos,val); upd(x); t[x].len=t[ls].len+find(rs,mid+1,r,t[ls].mx); int main() scanf("%d%d",&n,&m); for(int i=1,p;i<=m;i++) double x; scanf("%d%lf",&p,&x); change(1,1,n,p,x); printf("%d\n",t[1].len);
以上是关于[题解]luogu_P4198_楼房重建(线段树logn合并的主要内容,如果未能解决你的问题,请参考以下文章