• ZOJ 3349 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
    

    Author: CHEN, Zhangyi
    Contest: ZOJ Monthly, June 2010


    题目:给出一个序列,找出一个最长的子序列,相邻的两个数的差在d以内。

    很容易想到用dp (dp[i]=max(dp[j])+1)表示i从满足abs(a[i]-a[j])<=d的j所转移过来的最大值,每次维护这个最大值递推即可,复杂度为o(n^2)

    可以用线段树优化,用线段树处理出区间l到r的max(dp[j])然后进行状态转移,为o(nlogn)

    因为a[i]很大,所以要先进行坐标离散化处理再进行计算。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <string>
    #include <map>
    #include <cstring>
    #define INF 0x3f3f3f3f
    #define ms(x,y) memset(x,y,sizeof(x))
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int, int> P;
    
    const int maxn = 1e5 + 5;
    const int mod = 998244353;
    
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    int s[maxn];
    int san[maxn], tot;
    int sum[maxn << 2];
    
    void pushUp(int rt) 
    {
    	sum[rt] = max(sum[rt << 1], sum[rt << 1 | 1]);
    }
    
    void update(int pos, int c, int l, int r, int rt) 
    {
    	if (l == r) 
    	{
    		sum[rt] = c;
    		return;
    	}
    	int m = (l + r) >> 1;
    	if (pos <= m) update(pos, c, lson);
    	else update(pos, c, 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 ret = 0;
    	if (L <= m) ret = query(L, R, lson);
    	if (R > m) ret = max(ret, query(L, R, rson));
    	return ret;
    }
    
    int main() 
    {
    	int n, d;
    	while (~scanf("%d%d", &n, &d)) 
    	{
    		for (int i = 0; i < n; ++i)
    		{
    			scanf("%d", &s[i]);
    			san[i] = s[i];
    		}
    
    		tot = n;
    		sort(san, san + tot);
    		tot = unique(san, san + tot) - san;
    
    		ms(sum, 0);
    		int ans = 0;
    
    		for (int i = 0; i < n; i++) 
    		{
    
    			//本来是
    			//	l=lower_bound(san, san + tot, s[i] - d) - san
    			//	r = upper_bound(san, san + tot, s[i] + d) - san - 1;
    			//因为线段树维护1~n的区间,而l与r是从0开始的,所以统一向右移一位
    
    			int pos = lower_bound(san, san + tot, s[i]) - san + 1;
    			int l = lower_bound(san, san + tot, s[i] - d) - san + 1;
    			int r = upper_bound(san, san + tot, s[i] + d) - san;
    			int que = query(l, r, 1, tot, 1) + 1;	//dp[i]=max(dp[j]0+1  (a[j] >= a[i] - d && a[j] <= a[i] + d)
    
    			ans = max(ans, que);
    
    			update(pos, que, 1, tot, 1);
    		}
    		printf("%d
    ", ans);
    	}
    	return 0;
    }


    Fighting~
  • 相关阅读:
    Android 一个app启动另一个app
    Android 电池电量进度条,上下滚动图片的进度条(battery)
    Android 返回键双击退出程序
    Failed to load or instantiate
    GNUstep 快捷键编译
    Android 文件夹命名规范 国际化资源
    mac 安装protobuf,并编译为java,c++,python
    Android 贝塞尔曲线 折线图
    android 制作自定义标题栏
    Gson
  • 原文地址:https://www.cnblogs.com/Archger/p/12774727.html
Copyright © 2020-2023  润新知