zoukankan      html  css  js  c++  java
  • hdu4521 小明系列的问题——小明序列(LIS变种 (段树+单点更新解决方案))

    链接:

    huangjing

    题目:中文题目 

    思路:

    1:这个题目假设去掉那个距离大于d的条件,那么必定是一个普通的LIS。可是加上那个条件后就变得复杂了。我用的线段树的解法。

    。就是採用延迟更新的做法。用为距离要大于d啊,所以我们在循环到第i的时候,就对(i-d-1)这个点进行更新。由于假设在(i-d-1)这个点更新了,会对后面的造成影响。然后线段树的tree【】数组存的是以i结尾的最长lis,那么每次询问的时候就找最大的tree【】就能够了。。。

    2:dp的做法事实上跟线段树的思想一样,就是在对i进行询问的时候对i-p-1进行更新操作,这样就保证了增加g里面的书是间隔大于d的,那么就非常easy了。

    代码:

    小明系列问题——小明序列

    Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
    Total Submission(s): 1862    Accepted Submission(s): 569


    Problem Description
      大家都知道小明最喜欢研究跟序列有关的问题了,但是也就由于这样,小明差点儿已经玩遍各种序列问题了。

    可怜的小明苦苦地在各大站点上寻找着新的序列问题,但是找来找去都是自己早已研究过的序列。

    小明想既然找不到,那就自己来发明一个新的序列问题吧!

    小明想啊想,最终想出了一个新的序列问题,他欣喜若狂,由于是自己想出来的。于是将其新序列问题命名为“小明序列”。

      提起小明序列,他给出的定义是这种:
      ①首先定义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的情况下,“小明序列”中的元素须要多少个呢?

     

    Input
      输入数据多组。处理到文件结束;
      输入的第一行为两个正整数 n 和 d。(1<=n<=10^5 , 0<=d<=10^5)
      输入的第二行为n个整数A1 , A2 , A3 , ... , An,表示S序列的n个元素。(0<=Ai<=10^5)
     

    Output
      请对每组数据输出“小明序列”中的元素须要多少个,每组測试数据输出一行。

     

    Sample Input
    2 0 1 2 5 1 3 4 5 1 2 5 2 3 4 5 1 2
     

    Sample Output
    2 2 1
     

    Source
     

    Recommend
    liuyiding   |   We have carefully selected several similar problems for you:  5081 5080 5079 5078 5077 
     

    代码:

    1:线段树做法

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<vector>
    #include<cmath>
    #include<string>
    #include<queue>
    #define eps 1e-9
    #define ll long long
    #define INF 0x3f3f3f3f
    using namespace std;
    
    const int maxn=100000+10;
    
    int a[maxn],dp[maxn],n,d;//表示以i结尾的LIS
    int tree[maxn<<2];
    
    void push_up(int dex)
    {
        tree[dex]=max(tree[dex<<1],tree[dex<<1|1]);
    }
    
    void buildtree(int l,int r,int dex)
    {
        tree[dex]=0;
        if(l==r)  return;
        int mid=(l+r)>>1;
        buildtree(l,mid,dex<<1);
        buildtree(mid+1,r,dex<<1|1);
    }
    
    void Update(int pos,int l,int r,int dex,int value)
    {
        if(l==r)
        {
            tree[dex]=max(tree[dex],value);
            return;
        }
        int mid=(l+r)>>1;
        if(pos<=mid) Update(pos,l,mid,dex<<1,value);
        else Update(pos,mid+1,r,dex<<1|1,value);
        push_up(dex);
    }
    
    int Query(int l,int r,int L,int R,int dex)
    {
        if(L<=l&&R>=r)  return tree[dex];
        int mid=(l+r)>>1;
        if(R<=mid)  return Query(l,mid,L,R,dex<<1);
        else if(L>mid)  return Query(mid+1,r,L,R,dex<<1|1);
        else return max(Query(l,mid,L,R,dex<<1),Query(mid+1,r,L,R,dex<<1|1));
    }
    
    int main()
    {
        int temp,ans;
        while(~scanf("%d%d",&n,&d))
        {
            ans=temp=-1;
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                temp=max(temp,a[i]);
            }
            buildtree(0,temp,1);
            for(int i=1;i<=n;i++)
            {
                if(i-d-1>=1)  Update(a[i-d-1],0,temp,1,dp[i-d-1]);
                if(a[i]>=1)  dp[i]=Query(0,temp,0,a[i]-1,1)+1;
                else  dp[i]=1;
                ans=max(ans,dp[i]);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    

    2:dp做法

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define INF 0x3f3f3f3f
    using namespace std;
    
    const int maxn=100000+10;
    
    int a[maxn],dp[maxn],g[maxn],n,p;
    
    int main()
    {
        while(~scanf("%d%d",&n,&p))
        {
            int ans=-1;
            memset(dp,0,sizeof(dp));
            memset(g,INF,sizeof(g));
            for(int i=1;i<=n;i++)
               scanf("%d",&a[i]);
            for(int i=1;i<=n;i++)
            {
                if(i-p-1>0)  g[dp[i-p-1]]=min(a[i-p-1],g[dp[i-p-1]]);
                dp[i]=lower_bound(g+1,g+1+n,a[i])-g;
                ans=max(ans,dp[i]);
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    



    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    SP笔记:交叉实现七行并成一行
    HTML tag 学习
    操作哈希表
    Efficient bipedal robots based on passivedynamic walkers
    Pushing People Around
    ZEROMOMENT PONTTHIRTY FIVE YEARS OF ITS LIFE

    Active Learning for RealTime Motion Controllers
    Accelerometerbased User Interfaces for the Control of a Physically Simulated Character
    Dynamic Response for Motion Capture Animation
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4614629.html
Copyright © 2011-2022 走看看