• 楼房重建(线段树+单调栈)


    OvO

    • 线段树上维护一个单调栈,单点修改,查询(tr[1]).
    • 这个不用(pushdown),主要是难在(pushup)上。
    int Update(double M,int i,int l,int r){
        if(tr[i].Max<=M)return 0;
        if(a[l]>M)return tr[i].len;
        if(l==r)return a[l]>M;
        int mid=(l+r)>>1;
        if(tr[i<<1].Max<=M)return Update(M,i<<1|1,mid+1,r);
        else return tr[i].len-tr[i<<1].len+Update(M,i<<1,l,mid);
    }
    tr[i].len=tr[i<<1].len+Update(tr[i<<1].Max,i<<1|1,mid+1,r);
    

    因为对于一个更新来说,肯定是不能不要前半截的,也就是前面的不能选择式忽略。
    所以左儿子的(len)必须加上。然后去选择加上右儿子符合要求的长度。

    • (Update)里:
      如果右儿子中的最大值小于左儿子中的最大值,那就直接返回(0)就好。因为不可能有贡献了。
      如果右儿子的第一个就大于左儿子的最大值,那么右儿子的(len)值就全部满足条件了,所以直接返回(len)就好。
      如果这是个叶子节点的话,也是看值和左儿子最大值的关系。
      接下来设(s1)是右儿子的左儿子,(s2)是右儿子的右儿子。
      如果(s1.Max<=M),那么(s1)对答案已经做不了贡献了,直接返回(s2)的贡献即可。
      反之,则返回答案为从(s1)中找的符合要求的长度再加上右儿子的贡献即可。
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=1e5+1;
    int n,m;
    double a[maxn];
    struct E{double Max;int len;}tr[maxn<<2];
    int Update(double M,int i,int l,int r){
        if(tr[i].Max<=M)return 0;
        if(a[l]>M)return tr[i].len;
        if(l==r)return a[l]>M;
        int mid=(l+r)>>1;
        if(tr[i<<1].Max<=M)return Update(M,i<<1|1,mid+1,r);
        else return tr[i].len-tr[i<<1].len+Update(M,i<<1,l,mid);
    }
    void Change(int i,int l,int r,int pos,int k){
        if(l==r){
            tr[i].Max=(double)k/pos;
            tr[i].len=1;
            return;
        }int mid=(l+r)>>1;
        if(pos<=mid)Change(i<<1,l,mid,pos,k);
        else Change(i<<1|1,mid+1,r,pos,k);
        tr[i].Max=max(tr[i<<1].Max,tr[i<<1|1].Max);
        tr[i].len=tr[i<<1].len+Update(tr[i<<1].Max,i<<1|1,mid+1,r);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int k,pos;scanf("%d%d",&pos,&k);
            a[pos]=(double)k/pos;
            Change(1,1,n,pos,k);
            printf("%d
    ",tr[1].len);
        }
        return 0;
    }
    
  • 相关阅读:
    4.练习
    『Java面试题总结
    『Maven + Junit + Jacoco』单元测试覆盖率
    『Linux』命令
    『ElasticSearch』安装、健康值检查
    『类型转换』Object转Map、Map转Object
    『ElasticSearch』排序报错
    MD5加密解密网址总结
    汉字编码的理解
    ASCII码的理解
  • 原文地址:https://www.cnblogs.com/13ZY/p/13805602.html
Copyright © 2020-2023  润新知