zoukankan      html  css  js  c++  java
  • Special Subsequence(离散化线段树+dp)

    Special Subsequence

    Time Limit: 5 Seconds      Memory Limit: 32768 KB

    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
    ",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
    ",ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    无法定位程序输入点
    推荐一款免费看小说神器-连尚读书
    APP隐私权限审核规范
    移动互联网应用程序(APP) 启动屏广告行为规范
    [原创]A/B测试不是万能的,但没有是不行的?
    [原创]我的抖音号mayingbao,欢迎来交流
    [原创] push如何提高产品留存?
    [原创]创业公司中App专用术语
    [原创]app应用上架申请所需材料
    [原创]这37款APP,下架!做为测试人员,你应了解些这方面知识
  • 原文地址:https://www.cnblogs.com/handsomecui/p/5037473.html
Copyright © 2011-2022 走看看