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;
}