zoukankan      html  css  js  c++  java
  • hdu 4521 小明序列(线段树,DP思想)

    题意:

    ①首先定义S为一个有序序列,S={ A1 , A2 , A3 , ... , An },n为元素个数 ;
      ②然后定义Sub为S中取出的一个子序列,Sub={ Ai1 , Ai2 , Ai3 , ... , Aim },m为元素个数 ;
      ③其中Sub满足 Ai1 < Ai2 < Ai3 < ... < Aij-1 < Aij < Aij+1 < ... < Aim ;
      ④同时Sub满足对于任意相连的两个Aij-1与Aij都有 ij - ij-1 > d (1 < j <= m, d为给定的整数);
      ⑤显然满足这样的Sub子序列会有许许多多,而在取出的这些子序列Sub中,元素个数最多的称为“小明序列”(即m最大的一个Sub子序列)。
      例如:序列S={2,1,3,4} ,其中d=1;
      可得“小明序列”的m=2。即Sub={2,3}或者{2,4}或者{1,4}都是“小明序列”。

      当小明发明了“小明序列”那一刻,情绪非常激动,以至于头脑凌乱,于是他想请你来帮他算算在给定的S序列以及整数d的情况下,“小明序列”中的元素需要多少个呢?

    思路:

    DP的思想,但是只能想到N^2的算法。嘿嘿正好题目有说(0<=Ai<=10^5),那就是了,用线段树保存最值。

    每次做题都要考虑周全,边界什么的,,

    d=0时单独用贪心的方法算,其实不用也可以,。

    代码:

    int const N = 100005;
    
    int a[N], f[N];
    int F[N<<2];
    int n,d;
    
    
    
    void PushUp(int rt){
        F[rt]=max( F[rt<<1],F[rt<<1|1] );
        return;
    }
    
    void build(int l,int r,int rt){
        if(l==r){
            F[rt]=0;
            return;
        }
        int m=(l+r)>>1;
        build(lson);
        build(rson);
        PushUp(rt);
    }
    
    void update(int pos,int x,int l,int r,int rt){
        if(l==r){
            F[rt]=max( F[rt],x );
            return;
        }
        int m=(l+r)>>1;
        if(pos<=m)
            update(pos,x,lson);
        else
            update(pos,x,rson);
        PushUp(rt);
    }
    int query(int L,int R,int l,int r,int rt){
        if(L<=l && r<=R){
            return F[rt];
        }
        int m=(l+r)>>1;
        int res=0;
        if(L<=m)
            res=max( res,query(L,R,lson) );
        if(m<R)
            res=max( res,query(L,R,rson) );
        return res;
    }
    
    
    int proc1(){
        int d[N];
        int cn=0;
        d[0]=-1;
    
        rep(i,1,n){
            if(a[i]>d[cn]){
                d[++cn]=a[i];
            }else{
                int pos=lower_bound(d+1,d+1+cn,a[i])-d;
                d[pos]=a[i];
            }
        }
        return cn;
    }
    
    
    int main(){
    
        while(scanf("%d%d",&n,&d)!=EOF){
    
            int es=-inf;
    
            rep(i,1,n){
                scanf("%d",&a[i]);
                es=max( es,a[i] );
            }
    
            if(d==0){
                int ans=proc1();
                printf("%d
    ",ans);
            }else{
                build(0,es,1);
                int ans=1;
    
    
                rep(i,1,n){
                    if(i-d-1<=0){
                        f[i]=1;
                    }else{
                        update(a[i-d-1],f[i-d-1],0,es,1); //pos,x,l,r,rt
                        if(a[i]==0){
                            f[i]=1;
                            continue;
                        }
                        int t=query(0,a[i]-1,0,es,1); //L,R,l,r,rt
                        f[i]=t+1;
                        ans=max( ans,f[i] );
                    }
                }
                printf("%d
    ",ans);
            }
        }
    
        return 0;
    }
  • 相关阅读:
    14.使用nodejs将规定格式的txt转化为json数据
    13.resize妙用(书上看到的)
    12.写了一个怪怪的边框
    11.一起来抄一个小小的提示菜单
    UI02-textfiled.按钮 uibutton
    UI01-UIview UIlable的属性
    OC9-内存管理
    OC8-属性 KVC是键值编码
    OC7-‍ 类目,延展 协议代理。
    OC6-block-函数指针
  • 原文地址:https://www.cnblogs.com/fish7/p/4306005.html
Copyright © 2011-2022 走看看