[题解]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合并的主要内容,如果未能解决你的问题,请参考以下文章

P4198 楼房重建 |线段树

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

luogu P4198 楼房重建——线段树

P4198 楼房重建

P4198 楼房重建

[题解]luogu_P2824_HEOI2016排序(线段树/二分