• 线段树 bzoj2957 楼房重建


    大概意思就是求序列从一位置开始的动态上升序列。
    分块可过,但这一类题目其实可用线段树。
    也就是维护每个区间的上升序列长度。

    下面这种求法只是用于当前节点所覆盖的区间完全被查询区间覆盖。
    具体而言,查询时如果左儿子的max值< K,只去右儿子找。如果max_lc>=K,那么右儿子的长度全部符合,只要再递归着找左儿子即可。
    因为这道题要求的区间是1~n,所以是很裸的题。。。
    主体函数

    
    int q(double k,int x)
    {
        if(t[x].l==t[x].r)return k<t[x].h;
        if(t[x*2].h<k)return q(k,x*2+1);
        else return q(k,x*2)+t[x].sz-t[x*2].sz;
    }
    void up(int x)
    {
        t[x].h=max(t[x*2].h,t[x*2+1].h);
        t[x].sz=t[x*2].sz+q(t[x*2].h,x*2+1);
    }
    void C(int l,double k,int x)
    {
        if(t[x].l==t[x].r){t[x].sz=1;t[x].h=k;return;}
        int mid=t[x].l+t[x].r>>1;
        if(l<=mid)C(l,k,x*2);
        else C(l,k,x*2+1);
        up(x);
    }

    那么,对于求给定区间的呢
    其实就加了一个地方,只要递归到某个节点被询问区间完全覆盖即可,但要按照顺序枚举,并不断更新当前的最大高度,并累加答案。
    多的地方

    
        int q(int k,int x)
        {
            if(t[x].l==t[x].r){return k<t[x].h;}
            int mid=t[x].l+t[x].r>>1;
            if(t[x*2].h<k)return q(k,x*2+1);
            else return q(k,x*2)+t[x].szr-t[x*2].szr;
        }
        inline void Q_(int l,int r,int x)
        {
            if(t[x].l>=l&&t[x].r<=r)
                {h+=q(mh,x);mh=max(mh,t[x].h);return;}
            int mid=t[x].l+t[x].r>>1;
            if(l<=mid)Q_(l,r,x*2);
            if(r>mid)Q_(l,r,x*2+1);
        } 
        inline int Q(int l,int k)
        {
            h=1;mh=k;Q_(1,l,1);
            return h;
        }

    这道题的完整代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #define N 100005
    using namespace std;
    struct tree
    {
        int l,r,sz;double h;
    }t[N*4];
    int n,m;
    void build(int l,int r,int x)
    {
        t[x].l=l;t[x].r=r;
        if(l==r){t[x].sz=0;t[x].h=0.0;return;}
        int mid=l+r>>1;
        build(l,mid,x*2);
        build(mid+1,r,x*2+1);
    }
    
    int q(double k,int x)
    {
        if(t[x].l==t[x].r)return k<t[x].h;
        if(t[x*2].h<k)return q(k,x*2+1);
        else return q(k,x*2)+t[x].sz-t[x*2].sz;
    }
    void up(int x)
    {
        t[x].h=max(t[x*2].h,t[x*2+1].h);
        t[x].sz=t[x*2].sz+q(t[x*2].h,x*2+1);
    }
    void C(int l,double k,int x)
    {
        if(t[x].l==t[x].r){t[x].sz=1;t[x].h=k;return;}
        int mid=t[x].l+t[x].r>>1;
        if(l<=mid)C(l,k,x*2);
        else C(l,k,x*2+1);
        up(x);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        build(1,n,1);int x,y;
        while(m--)
        {
            scanf("%d%d",&x,&y);
            C(x,(double)y/x,1);
            printf("%d
    ",q(0,1));
        }
    }
  • 相关阅读:
    [原]openstack-kilo--issue(二) openstack auth error
    [原]关闭selinux
    [原]Failed to load SELinux policy. System Freezing ----redhat7or CentOS7 bug
    [转]Understanding OpenStack Authentication: Keystone PKI
    第七节:Core SignalR中的重连机制和心跳监测机制详解
    第八节:SQLServer函数大全(一)--字符串函数、数学函数
    第四节:SQLServer数据类型详解
    第三节:从多个角度分析顺序表和链表区别和特点
    第二节:线性表→顺序表→链表 逐个击破
    第一节:时间复杂度和空间复杂度
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7634648.html
Copyright © 2020-2023  润新知