• BZOJ 2957: 楼房重建 [线段树 信息合并]


    传送门

    题意:转换成斜率然后维护区间的上升序列(从区间第一个数开始的单调上升序列)


    区间保存这个区间的最长序列的长度$ls$和最大值$mx$

    如何合并两个区间信息?

    左区间一定选择,右区间递归寻找第一个大于左区间最大值$v$的位置

    具体来看,如果右区间的左最大值$<v$那么左面不可能选递归右面

    否则这个区间所选的右面一定选,减去左面的$ls$再递归左面

    合并复杂度$O(logn)$,总复杂度$O(nlog^2n)$

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define lc x<<1
    #define rc x<<1|1
    #define mid ((l+r)>>1)
    #define lson x<<1,l,mid
    #define rson x<<1|1,mid+1,r
    using namespace std;
    typedef long long ll;
    const int N=1e5+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n,Q,a,b;
    struct Node{
        int ls;
        double mx;
        Node():ls(0),mx(0.0){}
    }t[N<<2];
    int cal(int x,int l,int r,double v){
        if(l==r) return t[x].mx>v;
        if(t[lc].mx<=v) return cal(rson,v);
        else return t[x].ls-t[lc].ls+cal(lson,v);
    }
    inline void merge(int x,int l,int r){
        t[x].mx=max(t[lc].mx,t[rc].mx);
        t[x].ls=t[lc].ls+cal(rson,t[lc].mx);
    }
    void segCha(int x,int l,int r,int p,double v){
        if(l==r) t[x].ls=1,t[x].mx=v;
        else{
            if(p<=mid) segCha(lson,p,v);
            if(mid<p) segCha(rson,p,v);
            merge(x,l,r);
        }
    }
    int main(){
        freopen("in","r",stdin);
        n=read();Q=read();
        while(Q--){
            a=read();b=read();
            segCha(1,1,n,a,(double)b/a);
            printf("%d
    ",t[1].ls);
        }
    }
  • 相关阅读:
    vue-cli脚手架 安装
    音视频
    移动端开发问题
    GIT提交命令清单
    关于cookie和$.cookie
    emoji表情进行编码以适配移动端用户emoji表情的输入和展示
    父组件如何使用子组件中的方法
    uniapp实现锚点跳转
    uniapp判断android还是iOS
    uniapp动态设置当前页面标题
  • 原文地址:https://www.cnblogs.com/candy99/p/6490420.html
Copyright © 2020-2023  润新知