zoukankan      html  css  js  c++  java
  • 线段树 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));
        }
    }
  • 相关阅读:
    线段树模板(HDU 6356 Glad You Came)
    Treap模板
    Codeforces Round #499 (Div. 2) D. Rocket题解
    Codeforces Round #499 (Div. 2) C Fly题解
    KMP与AC自动机模板
    HDU 6351 Naive Operations(线段树)
    python核心编程第六章练习6-13
    python核心编程第六章练习6-12
    [转]我为什么要学习python
    python核心编程第六章练习6-11
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7634648.html
Copyright © 2011-2022 走看看