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;
    }
  • 相关阅读:
    SpringCloud------熔断与降级
    Linux中的defunct进程(僵尸进程)
    网站论坛收藏
    同步与阻塞,异步与非阻塞的区别
    Linux下批量杀掉筛选进程
    MapReduce运行原理和过程
    TF-IDF原理
    如何解决VMware 虚拟机不能铺满屏幕
    桥接和nat连接
    http: server gave HTTP response to HTTPS client & Get https://192.168.2.119/v2/: dial tcp 192.168.2.119:443: getsockopt: connection refused
  • 原文地址:https://www.cnblogs.com/fish7/p/4306005.html
Copyright © 2011-2022 走看看