• BZOJ 4553 [Tjoi2016&Heoi2016]序列


    题解:我现在真的怀疑自己的语文水平

    用f[i]表示以i为结尾的最长上升子序列

    然后找前面的j转移

    f[i]=max{f[j]}+1 (j<=i&&max[j]<=a[i]&&a[j]<=min[i])

    这是偏序关系,用树套树或CDQ分治解决

    //mx[j]<=a[i]
    //a[j]<=mn[i]
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define lo now<<1
    #define ro now<<1|1
    using namespace std;
    const int maxn=100009;
    const int lgn=30;
    
    int n,m;
    int ans=0;
    int f[maxn]={0},mx[maxn],mn[maxn],v[maxn];
    
    int nn=0;
    int fa[maxn*lgn]={0},ch[maxn*lgn][2]={0},ky[maxn*lgn]={0},nowf[maxn*lgn]={0},mxf[maxn*lgn]={0};
    int son(int x){
        if(ch[fa[x]][0]==x)return 0;
        else return 1;
    }
    void pushup(int x){
        mxf[x]=max(nowf[x],max(mxf[ch[x][0]],mxf[ch[x][1]]));
    }
    
    void Rotate(int &root,int x){
        int y=fa[x];
        int z=fa[y];
        int b=son(x),c=son(y);
        int a=ch[x][b^1];
        if(z)ch[z][c]=x;
        else root=x;
        fa[x]=z;
        if(a)fa[a]=y;
        ch[y][b]=a;
        fa[y]=x;ch[x][b^1]=y;
        pushup(y);pushup(x);
    }
    void Splay(int &root,int x,int i){
        while(fa[x]!=i){
            int y=fa[x];
            int z=fa[y];
            if(z==i){
                Rotate(root,x);
            }else{
                if(son(x)==son(y)){
                    Rotate(root,y);Rotate(root,x);
                }else{
                    Rotate(root,x);Rotate(root,x);
                }
            }
        }
    }
    
    void Ins(int &root,int p){
        int x=root,y=0;
        while(x){
            y=x;
            if(mx[p]<=ky[x]){
                x=ch[x][0];
            }else{
                x=ch[x][1];
            }
        }
        x=++nn;
        fa[x]=y;ky[x]=mx[p];nowf[x]=f[p];mxf[x]=nowf[x];
        if(!y){
            root=x;
        }else{
            if(ky[x]<=ky[y])ch[y][0]=x;
            else ch[y][1]=x;
        }
        Splay(root,x,0);
    }
    
    int Getmxf(int x,int val){
        int ret=0;
        while(x){
            if(ky[x]<=val){
                ret=max(ret,max(mxf[ch[x][0]],nowf[x]));
                x=ch[x][1];
            }else{
                x=ch[x][0];
            }
        }
        return ret;
    }
    
    struct SegmentTree{
        int l,r;
        int root;
    }tree[maxn<<2];
    void BuildTree(int now,int l,int r){
        tree[now].l=l;tree[now].r=r;tree[now].root=0;
        if(l==r)return;
        int mid=(l+r)>>1;
        BuildTree(lo,l,mid);
        BuildTree(ro,mid+1,r);
    }
    
    void Insertpoint(int now,int pla,int p){
        Ins(tree[now].root,p);
        if(tree[now].l==tree[now].r)return;
        int mid=(tree[now].l+tree[now].r)>>1;
        if(pla<=mid)Insertpoint(lo,pla,p);
        else Insertpoint(ro,pla,p);
    }
    
    int Querymax(int now,int ll,int rr,int val){
        if(tree[now].l>=ll&&tree[now].r<=rr){
            return Getmxf(tree[now].root,val);
        }
        int mid=(tree[now].l+tree[now].r)>>1;
        int ret=0;
        if(ll<=mid)ret=max(ret,Querymax(lo,ll,rr,val));
        if(rr>mid)ret=max(ret,Querymax(ro,ll,rr,val));
        return ret;
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i){
            scanf("%d",&v[i]);
            mx[i]=mn[i]=v[i];
        }
        while(m--){
            int x,y;
            scanf("%d%d",&x,&y);
            mx[x]=max(mx[x],y);
            mn[x]=min(mn[x],y);
        }
        
        BuildTree(1,1,100000);
        
        for(int i=1;i<=n;++i){
            f[i]=Querymax(1,1,mn[i],v[i])+1;
            Insertpoint(1,v[i],i);
            ans=max(ans,f[i]);
        }
        
        printf("%d
    ",ans);
        return 0;
    }
    自己还是太辣鸡了
  • 相关阅读:
    影响stm32仿真的因素
    DMA 如何查看它有没有传输完成 传输完成再开启
    keil出错总结
    一个例子讲解wav头文件 stm32声音程序 录音和播放 wav
    前期绑定 vs 后期绑定
    抽象类 VS 接口 (3)
    抽象类 VS 接口(1)
    封装之--JAVA中的访问修饰符(区别于.NET)
    【DP专题】——洛谷P1156垃圾陷阱
    MySql
  • 原文地址:https://www.cnblogs.com/zzyer/p/8576450.html
Copyright © 2020-2023  润新知