zoukankan      html  css  js  c++  java
  • 【bzoj4553】[Tjoi2016&Heoi2016]序列【树套树 树状数组套平衡树】

    洛谷传送门
    大视野传送门
    这道题刚开始看上去没有思路,不过慢慢分析有了。
    我们设3个数组:
    a[i]表示原来第i个位置上的值。
    maxn[i]表示第i个位置上可以变成的最大值。
    minn[i]表示第i个位置上可以变成的最小值。
    要满足在任意一种变化中,选出的子序列中第i个位置的上一个位置j是符合要求的,需要满足:
    1.j<i 这一条很显然。
    2.maxn[j]<=a[i] 当j的位置上的数变成最大值时序列仍然不降。
    3.a[j]<=minn[i] 当i的位置上的数变成最小值时序列仍然不降。
    于是一个dp就很显然了:
    f[i]=max(f[j]),j要满足上述条件。
    可以发现,有1,2,3这3条要求,不就是一个三维偏序问题吗?跟陌上花开那道题非常像。
    首先从小到大枚举i,可以降掉第一维。
    第二维和第三维直接树套树搞定。
    我写了树状数组套Treap,时间复杂度和空间复杂度都是比较稳的。
    第一次1A树套树祭
    代码:

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    const int N=100005;
    int n,m,k,x,y,ans=1,a[N],maxn[N],minn[N],f[N];
    int cnt,ch[N*16][2],siz[N*16],val[N*16],key[N*16],mx[N*16],rnd[N*16];
    struct Treap{
        int rt;
        void pushup(int k){
            siz[k]=siz[ch[k][0]]+siz[ch[k][1]]+1;
            mx[k]=max(max(mx[ch[k][0]],mx[ch[k][1]]),key[k]);
        }
        void rotate(int &y,int md){
            int x=ch[y][md];
            ch[y][md]=ch[x][!md];
            ch[x][!md]=y;
            pushup(y);
            pushup(x);
            y=x;
        }
        void insert(int &k,int v,int x){
            if(!k){
                k=++cnt;
                val[k]=v;
                key[k]=mx[k]=x;
                rnd[k]=rand();
                siz[k]=1;
                return;
            }
            siz[k]++;
            if(v==val[k]){
                key[k]=max(key[k],x);
            }else if(v<val[k]){
                insert(ch[k][0],v,x);
                if(rnd[ch[k][0]]>rnd[k]){
                    rotate(k,0);
                }
            }else{
                insert(ch[k][1],v,x);
                if(rnd[ch[k][1]]>rnd[k]){
                    rotate(k,1);
                }
            }
            pushup(k);
        }
        int query(int x){
            int k=rt,res=0;
            while(k){
                if(x==val[k]){
                    res=max(res,key[k]);
                    break;
                }else if(x<val[k]){
                    k=ch[k][0];
                }else{
                    res=max(res,max(key[k],mx[ch[k][0]]));
                    k=ch[k][1];
                }
            }
            return res;
        }
    }t[N];
    inline int lowbit(int x){
        return x&(-x);
    }
    void add(int i,int j,int v){
        while(i<=k){
            t[i].insert(t[i].rt,j,v);
            i+=lowbit(i);
        }
    }
    int qmax(int i,int j){
        int res=0;
        while(i){
            res=max(res,t[i].query(j));
            i-=lowbit(i);
        }
        return res;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            maxn[i]=minn[i]=a[i];
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d",&x,&y);
            maxn[x]=max(maxn[x],y);
            minn[x]=min(minn[x],y);
            k=max(k,maxn[x]);
        }
        f[1]=1;
        add(maxn[1],a[1],1);
        for(int i=2;i<=n;i++){
            f[i]=qmax(a[i],minn[i])+1;
            add(maxn[i],a[i],f[i]);
            ans=max(ans,f[i]);
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    2018-8-10-win10-uwp-商业游戏-1.2.1
    2018-8-10-win10-uwp-商业游戏-1.2.1
    2019-3-1-获取-Nuget-版本号
    2019-3-1-获取-Nuget-版本号
    2019-9-24-dotnet-remoting-抛出异常
    2019-9-24-dotnet-remoting-抛出异常
    2018-2-13-C#-解析-sln-文件
    2018-2-13-C#-解析-sln-文件
    2018-10-19-jekyll-添加-Valine-评论
    2018-10-19-jekyll-添加-Valine-评论
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476897.html
Copyright © 2011-2022 走看看