【线段树】 ZOJ 3349 Special Subsequence
求最长的一种序列 这种序列满足 前一项与后一项相差小于d
先离散化
每次取a[i]-d 与 a[i]+d 中的最大值
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <string> #include <iostream> #include <algorithm> #include <sstream> using namespace std; #include <queue> #include <stack> #include <vector> #include <deque> #include <set> #include <map> #define cler(arr, val) memset(arr, val, sizeof(arr)) #define IN freopen ("in.txt" , "r" , stdin); #define OUT freopen ("out.txt" , "w" , stdout); typedef long long LL; const int MAXN = 100010;//点数的最大值 const int MAXM = 20006;//边数的最大值 const int INF = 11521204; const int mod=123456789; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int sum[MAXN<<2],col[MAXN<<2],a[MAXN],b[MAXN],tol,dp[MAXN]; void pushup(int rt) { sum[rt]=max(sum[rt<<1],sum[rt<<1|1]); } void build(int l,int r,int rt) { col[rt]=0; if(l==r) { sum[rt]=0; return ; } int m=(l+r)>>1; build(lson); build(rson); pushup(rt); } void update(int add,int R,int l,int r,int rt) { if(l==r) { sum[rt]=add; return ; } int m=(l+r)>>1; if(R<=m) update(add,R,lson); else update(add,R,rson); pushup(rt); } int query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) { return sum[rt]; } int m=(l+r)>>1; int res=0; if(L<=m) res=max(res,query(L,R,lson)); if(m<R) res=max(res,query(L,R,rson)); return res; } int main() { int n,m; //IN; while(scanf("%d%d",&n,&m)!=EOF) { cler(dp,0); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); b[i]=a[i]; } sort(b+1,b+1+n); tol=1; for(int i=2;i<=n;i++) if(b[i]!=b[i-1]) b[++tol]=b[i]; build(1,n,1); int ans=0; for(int i=1;i<=n;i++) { int x=lower_bound(b+1,b+1+tol,a[i])-b; int l=lower_bound(b+1,b+1+tol,a[i]-m)-b; int r=upper_bound(b+1,b+1+tol,a[i]+m)-b-1; int k=query(l,r,1,n,1); ans=max(ans,k+1); update(k+1,x,1,n,1); } printf("%d\n",ans); } return 0; }