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 }