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