Special Subsequence(离散化线段树+dp)
There a sequence S with n integers , and A is a special subsequence that satisfies |Ai-Ai-1| <= d ( 0 <i<=|A|))
Now your task is to find the longest special subsequence of a certain sequence S
Input
There are no more than 15 cases , process till the end-of-file
The first line of each case contains two integer n and d ( 1<=n<=100000 , 0<=d<=100000000) as in the description.
The second line contains exact n integers , which consist the sequnece S .Each integer is in the range [0,100000000] .There is blank between each integer.
There is a blank line between two cases
Output
For each case , print the maximum length of special subsequence you can get.
Sample Input
5 2 1 4 3 6 5 5 0 1 2 3 4 5
Sample Output
3 1
题解:让求|Ai-Ai-1| <= d 的最长子序列;
很简单就想到DP;
dp[i]表示前i个数的最长为多少,
则dp[i]=max(dp[j]+1) abs(a[i]-a[j])<=d
不出意外,肯定超时了;
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<vector> #include<queue> #include<stack> #include<map> using namespace std; const int INF=0x3f3f3f3f; const double PI=acos(-1.0); typedef long long LL; #define mem(x,y) memset(x,y,sizeof(x)) #define PI(x) printf("%d",x) #define PL(x) printf("%lld",x) #define SI(x) scanf("%d",&x) #define SL(x) scanf("%lld",&x) #define P_ printf(" ") #define T_T while(T--) const int MAXN=100010; int dp[MAXN]; int m[MAXN]; int main(){ int n,d; while(~scanf("%d%d",&n,&d)){ for(int i=0;i<n;i++)SI(m[i]); mem(dp,0); int ans=0; for(int i=0;i<n;i++){ for(int j=0;j<i;j++){ if(abs(m[i]-m[j])<=d){ dp[i]=max(dp[i],dp[j]+1); ans=max(ans,dp[i]); } } } printf("%d\n",ans+1); } return 0; }
接下来就是如何高效地找到满足差值在d以内的最大值。
将数字进行离散化,对于一个新的数,就可以确定一个范围,然后在这个范围进行查找dp的最值+1即可。
线段树每一个结点保存的是这个区间的最值,叶子结点的值便是以这个数结尾的最长数量;
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<vector> #include<queue> #include<stack> #include<map> using namespace std; const int INF=0x3f3f3f3f; const double PI=acos(-1.0); typedef long long LL; #define mem(x,y) memset(x,y,sizeof(x)) #define PI(x) printf("%d",x) #define PL(x) printf("%lld",x) #define SI(x) scanf("%d",&x) #define SL(x) scanf("%lld",&x) #define P_ printf(" ") #define T_T while(T--) #define ll root<<1 #define rr root<<1|1 #define lson ll,l,mid #define rson rr,mid+1,r #define V tree[root] const int MAXN=100010; int tree[MAXN<<2]; int a[MAXN],b[MAXN]; int dp[MAXN]; int nm; int pushup(int root){ tree[root]=max(tree[ll],tree[rr]); } void update(int root,int l,int r,int nt,int v){ int mid=(l+r)>>1; if(l==r){ V=v;return; } if(mid>=nt)update(lson,nt,v); else update(rson,nt,v); pushup(root); } void query(int root,int l,int r,int L,int R){ if(l>=L&&r<=R){ nm=max(nm,V); return; } int mid=(l+r)>>1; if(mid>=L)query(lson,L,R); if(mid<R)query(rson,L,R); } int main(){ int n,d; while(~scanf("%d%d",&n,&d)){ for(int i=0;i<n;i++)SI(a[i]),b[i]=a[i]; sort(b,b+n); mem(tree,0);mem(dp,0); for(int i=0;i<n;i++){ int l,r; l=lower_bound(b,b+n,a[i]-d)-b+1; r=upper_bound(b,b+n,a[i]+d)-b+1-1; nm=0; query(1,1,n,l,r); dp[i]=nm+1; update(1,1,n,lower_bound(b,b+n,a[i])-b+1,dp[i]); } int ans=0; for(int i=0;i<n;i++)ans=max(ans,dp[i]); printf("%d\n",ans); } return 0; }