2 0 1 2 5 1 3 4 5 1 2 5 2 3 4 5 1 2
2 2 1
#include <iostream> #include<stdio.h> #include<string.h> using namespace std; const int maxn=100010; int maxv[maxn<<2],dp[maxn],val[maxn],pre[maxn]; void update(int L,int R,int p,int d,int k) { int ls,rs,mid; if(L==R) { maxv[k]=max(maxv[k],d); return ; } ls=k<<1; rs=ls|1; mid=(L+R)>>1; if(p<=mid) update(L,mid,p,d,ls); else update(mid+1,R,p,d,rs); maxv[k]=max(maxv[ls],maxv[rs]); } int qu(int L,int R,int l,int r,int k)//区间最值 { int ls,rs,mid; if(l==L&&r==R) return maxv[k]; ls=k<<1; rs=ls|1; mid=(L+R)>>1; if(l>mid) return qu(mid+1,R,l,r,rs); else if(r<=mid) return qu(L,mid,l,r,ls); else return max(qu(L,mid,l,mid,ls),qu(mid+1,R,mid+1,r,rs)); } int main() { int n,d,i,lim,ans; while(~scanf("%d%d",&n,&d)) { memset(maxv,0,sizeof maxv); memset(dp,0,sizeof dp); lim=0,ans=1; for(i=1;i<=n;i++) { scanf("%d",&val[i]); val[i]+=2; lim=max(lim,val[i]); } for(i=1;i<=d;i++) dp[val[i]]=1,pre[i]=1;//pre起到队列的作用。先把要跟新的值存起来。等距离大于d的时候再更新 for(i=d+1;i<=n;i++) { if(i==1)//d=0单独处理下 { dp[val[i]]=1; pre[i-d]=1; update(1,lim,val[i-d],pre[i-d],1); continue; } dp[val[i]]=max(qu(1,lim,1,val[i]-1,1)+1,dp[val[i]]); pre[i]=dp[val[i]]; update(1,lim,val[i-d],pre[i-d],1); ans=max(ans,dp[val[i]]); } printf("%d\n",ans); } return 0; }
hdu 4521 小明系列问题——小明序列(线段树+DP),布布扣,bubuko.com
原文:http://blog.csdn.net/bossup/article/details/24307619