hdu4521 小明系列问题——小明序列(LIS变种 (线段树+单点更新解法))

来源:互联网 发布:js array对象 清空 编辑:程序博客网 时间:2024/05/21 09:32

链接:

huangjing

题目:中文题目 

思路:

1:这个题目如果去掉那个距离大于d的条件,那么必然是一个普通的LIS,但是加上那个条件后就变得复杂了。我用的线段树的解法。。。就是采用延迟更新的做法,用为距离要大于d啊,所以我们在循环到第i的时候,就对(i-d-1)这个点进行更新,因为如果在(i-d-1)这个点更新了,会对后面的造成影响,然后线段树的tree【】数组存的是以i结尾的最长lis,那么每次询问的时候就找最大的tree【】就可以了。。。

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

代码:

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

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 01 25 13 4 5 1 25 23 4 5 1 2
 

Sample Output
221
 

Source
2013腾讯编程马拉松初赛第四场(3月24日)
 

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 0x3f3f3f3fusing namespace std;const int maxn=100000+10;int a[maxn],dp[maxn],n,d;//表示以i结尾的LISint 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\n",ans);    }    return 0;}

2:dp做法

代码:

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define INF 0x3f3f3f3fusing 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;}



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 游戏全屏时卡了无法退到界面怎么办 u盘插电脑上提示有病毒怎么办 三星手机文件怎么删除不掉怎么办 用夜神模拟器玩第五人格太卡怎么办 雷电模拟器玩刺激战场太卡了怎么办 绝地求生刺激战场模拟器太卡怎么办 ddj sb2打碟功能没了怎么办 驼背怎么办 要能快速矫正的方法 苹果7中间的home键坏了怎么办 苹果6p的home键不管用怎么办 华为获取数据失败请检查网络怎么办 三星手机未解锁刷机变砖怎么办 手机显示充电但是充不进去怎么办 手机拔出显示无法连接移动网怎么办 手机上的音乐老是显示网络忙怎么办 华为手机账号换手机忘记密码怎么办 墨墨背单词的注册邮箱忘了怎么办 华为手机华为账号密码忘记了怎么办 手机玩游戏降频特别厉害怎么办 苹果应用商店id登录老卡怎么办 苹果id忘记了自动续费怎么办 红米手机小米账号密码忘了怎么办 小米5splus没系统卡米怎么办 注册谷歌账号输入手机好怎么办 谷歌注册电话号码用了太多次怎么办 内存卡用了深度清理的软件怎么办 华为畅享5s密码忘了怎么办 小米5s进水了一直开机关机怎么办 手机菜单键功能键返回键失灵怎么办 小米5s更新系统发热严重怎么办 小米手机4G网速不好怎么办力 红米5 plus开不开机怎么办 小米3s手机触屏部分失灵怎么办 魅族手机屏幕锁密码忘了怎么办 手机没设置魅族账号密码忘了怎么办 魅族手机格式化密码忘了怎么办 魅族手机忘记密码了怎么解锁怎么办 手机设置的应用加密忘记密码怎么办 手机上设置应用加密忘记密码怎么办 魅蓝flyme密码忘了怎么办图片 魅族手机经常自动账号锁屏怎么办