1 /*
2 题意:给你n的序列求最长子序列,该序列里|a[i]-a[i-1]|<=d
3
4 分析:O(n^2)的DP很容易想到,那么显然优化也很容易想到
5 用线段树维护区间最大值,
6 设dp[i]表示以数值为i结尾的最长符合要求序列,
7 对于a[i],询问值为[a[i]-d,a[i]+d]的最大值,然后在单点更新;
8 注意要先离散;
9
10
11
12 */
13
14 #include<cstdio>
15 #include<cstring>
16 #include<cstdlib>
17 #include<iostream>
18 #include<cmath>
19 #include<algorithm>
20 #include<vector>
21 #define lson l,m,rt<<1
22 #define rson m+1,r,rt<<1|1
23 using namespace std;
24 const int N=100000+10;
25 int mx[N<<2];
26 vector<int> X;
27 int n,d,n1;
28 int a[N];
29 void init(){
30 sort(X.begin(),X.end());
31 n1=unique(X.begin(),X.end())-X.begin();
32 }
33 void pushup(int rt){
34 mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
35 }
36 void update(int L,int v,int l,int r,int rt){
37 if (l==r){
38 if(v>mx[rt]) mx[rt]=v;
39 return;
40 }
41 int m=(l+r)>>1;
42 if (L<=m) update(L,v,lson);
43 else update(L,v,rson);
44 pushup(rt);
45 }
46 int query(int L,int R,int l,int r,int rt){
47 if (L<=l && r<=R){
48 return mx[rt];
49 }
50 int m=(l+r)>>1;
51 int t1=0,t2=0;
52 if (L<=m) t1=query(L,R,lson);
53 if (m< R) t2=query(L,R,rson);
54 return max(t1,t2);
55 }
56 void work(){
57 memset(mx,0,sizeof(mx));
58 int ret=0;
59 int t=lower_bound(X.begin(),X.begin()+n1,a[0])-X.begin();
60 update(t,1,0,N-1,1);
61 for (int i=1;i<n;i++){
62 int l=lower_bound(X.begin(),X.begin()+n1,a[i]-d)-X.begin();
63 int r=upper_bound(X.begin(),X.begin()+n1,a[i]+d)-X.begin()-1;
64 // cout<<i<<" "<<l<<" "<<r<<" ";
65 int t=query(l,r,0,N-1,1);
66 // cout<<t<<endl;
67 if (t+1>ret) ret=t+1;
68 int c=lower_bound(X.begin(),X.begin()+n1,a[i])-X.begin();
69 update(c,t+1,0,N-1,1);
70 }
71 printf("%d\n",ret);
72 }
73 int main(){
74 while (~scanf("%d%d",&n,&d)){
75 X.clear();
76 for (int i=0;i<n;i++){
77 scanf("%d",&a[i]);
78 X.push_back(a[i]);
79 }
80 init();
81 work();
82 }
83 return 0;
84 }