小明系列问题——小明序列
2013-03-25 18:52
211 查看
大家都知道小明最喜欢研究跟序列有关的问题了,可是也就因为这样,小明几乎已经玩遍各种序列问题了。可怜的小明苦苦地在各大网站上寻找着新的序列问题,可是找来找去都是自己早已研究过的序列。小明想既然找不到,那就自己来发明一个新的序列问题吧!小明想啊想,终于想出了一个新的序列问题,他欣喜若狂,因为是自己想出来的,于是将其新序列问题命名为“小明序列”。
提起小明序列,他给出的定义是这样的:
①首先定义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[i]为以Ai结尾满足小明序列要求的最长子序列的长度,我们可用线段树来维护这n个位置。但是只用线段树还不够,我们首先将Ai排一个序,先按Ai的大小从小到大排列,若数字相等则按位置从大到小排列。这样我们按排列后的序列依次求dp[i],然后更新线段树中对应的值。具体做法是:我们设当前我们要求的数字的位置是po,则我们只要在线段树中求区间[1,po-d-1]的最大值再加上1即为所求,为什么呢,因为经过排序后,我们在求位置dp[po]时,我们可以保证前面所求的数要么数字比当前求的小,要么位置在po之后(从而不影响dp[po]的值),所以这样做是对的。求完之后不要忘了更新线段树,将第po个数赋值为dp[po]。代码如下:
提起小明序列,他给出的定义是这样的:
①首先定义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[i]为以Ai结尾满足小明序列要求的最长子序列的长度,我们可用线段树来维护这n个位置。但是只用线段树还不够,我们首先将Ai排一个序,先按Ai的大小从小到大排列,若数字相等则按位置从大到小排列。这样我们按排列后的序列依次求dp[i],然后更新线段树中对应的值。具体做法是:我们设当前我们要求的数字的位置是po,则我们只要在线段树中求区间[1,po-d-1]的最大值再加上1即为所求,为什么呢,因为经过排序后,我们在求位置dp[po]时,我们可以保证前面所求的数要么数字比当前求的小,要么位置在po之后(从而不影响dp[po]的值),所以这样做是对的。求完之后不要忘了更新线段树,将第po个数赋值为dp[po]。代码如下:
#include <iostream> #include <string.h> #include <stdio.h> #include <algorithm> #define maxn 100010 #define mid ((t[p].l+t[p].r)>>1) #define ls (p<<1) #define rs (ls|1) using namespace std; struct tree { int l,r; int max; }t[maxn<<2]; int max(int a,int b) { return a>b?a:b; } void pushup(int p) { t[p].max=max(t[ls].max,t[rs].max); } void build(int p,int l,int r) { t[p].l=l,t[p].r=r; if(l==r) { t[p].max=0; return; } build(ls,l,mid); build(rs,mid+1,r); pushup(p); } void change(int p,int x,int val) { if(t[p].l==t[p].r) { t[p].max=val; return; } if(x>mid) change(rs,x,val); else change(ls,x,val); pushup(p); } int query(int p,int l,int r) { if(l>r) return 0; if(t[p].l==l&&t[p].r==r) { return t[p].max; } if(l>mid) return query(rs,l,r); else if(r<=mid) return query(ls,l,r); else return max(query(ls,l,mid),query(rs,mid+1,r)); } struct node { int po; int num; }a[maxn]; bool cmp(node a,node b) { if(a.num==b.num) return a.po>b.po; return a.num<b.num; } int main() { // freopen("dd.txt","r",stdin); int n,d; while(scanf("%d%d",&n,&d)!=EOF) { int i; build(1,1,n); for(i=1;i<=n;i++) { scanf("%d",&a[i].num); a[i].po=i; } sort(a+1,a+n+1,cmp); int ans=0; for(i=1;i<=n;i++) { int po=a[i].po,tmp=query(1,1,po-d-1); ans=max(ans,tmp+1); change(1,po,tmp+1); } printf("%d\n",ans); } return 0; }
相关文章推荐
- hdu4521小明系列问题——小明序列
- HDU 4521 小明系列问题——小明序列 LIS+动态规划
- 小明系列问题——小明序列
- HDU 4521 小明系列问题——小明序列
- 【线段树】 HDOJ 4521 小明系列问题——小明序列
- Hdu 4521 小明系列问题——小明序列【lis 变形】
- hdu 5421 小明系列问题——小明序列(LIS最长上升子序列)
- 杭电4521小明系列问题——小明序列
- HDU4521:小明系列问题——小明序列(LIS加强版)
- hdu 4521 小明系列问题——小明序列 线段树+二分
- 线段树(端点更新) hdu-4521 小明系列问题——小明序列
- 小明系列问题——小明序列 (线段树优化的最长上升子序列)
- hdoj 4521 小明系列问题——小明序列 【线段树优化dp or LIS变形】
- 【hdu】4521 小明系列问题——小明序列【LIS变种】
- hdu_4521_小明系列问题——小明序列(LIS)
- HDU4521:小明系列问题——小明序列(推广LIS(带区间))
- hdu4521 小明系列问题——小明序列(线段树做法)
- hdu-45221-小明系列问题——小明序列-(线段树)
- HDU 4521 小明系列问题--小明序列(加强版LIS+线段树单点更新)
- hdu_4521_小明系列问题——小明序列(LIS)