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
定义D序列:序列里相邻元素差的绝对值不超过d。
题意:给定n个元素组成的序列a[],求最长的D序列。
思路:考虑升序排列的序列,那么则有dp[i] = max(dp[j]) (l <= j <= r)。其中a[l]为大于或者等于a[i]-d的第一个数,a[r]为小于或者等于a[i]+d的最后一个数。维护升序序列,并不丢失序列元素的下标,可以先将坐标离散化。考虑对当前元素a[i]的处理,我们只需要处理出a[l] >= a[i] - d,a[r] <= a[i] + d以及a[i]在离散化序列中的下标L, R, P,用线段树维护[L, R]区间的最大值,更新到P对应的区间上。只要在这个过程中维护序列长度即可。
偷懒用了C++lower_boundWA了两次。还是自己手写好。。。
AC代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#define INF 0x3f3f3f
#define eps 1e-4
#define MAXN (200000+10)
#define MAXM (100000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
using namespace std;
int a[MAXN], rec[MAXN];
int dp[MAXN];
struct Tree
{
int l, r;
int Max;
};
Tree tree[MAXN<<2];
void PushUp(int o){
tree[o].Max = max(tree[ll].Max, tree[rr].Max);
}
void Build(int o, int l, int r)
{
tree[o].l = l; tree[o].r = r;
tree[o].Max = 0;
if(l == r)
return ;
int mid = (l + r) >> 1;
Build(lson); Build(rson);
PushUp(o);
}
void update(int o, int pos, int v)
{
if(tree[o].l == tree[o].r)
{
tree[o].Max = v;
return ;
}
int mid = (tree[o].l + tree[o].r) >> 1;
if(pos <= mid)
update(ll, pos, v);
else
update(rr, pos, v);
PushUp(o);
}
int Query(int o, int L, int R)
{
if(L <= tree[o].l && R >= tree[o].r)
return tree[o].Max;
int mid = (tree[o].l + tree[o].r) >> 1;
if(R <= mid)
return Query(ll, L, R);
else if(L > mid)
return Query(rr, L, R);
else
return max(Query(ll, L, mid), Query(rr, mid+1, R));
}
int Findleft(int val, int l, int r)
{
int ans;
while(r >= l)
{
int mid = (l + r) >> 1;
if(rec[mid] >= val)
{
r = mid-1;
ans = mid;
}
else
l = mid+1;
}
return ans;
}
int Findright(int val, int l, int r)
{
int ans;
while(r >= l)
{
int mid = (l + r) >> 1;
if(rec[mid] <= val)
{
l = mid+1;
ans = mid;
}
else
r = mid-1;
}
return ans;
}
int Findpos(int val, int l, int r)
{
while(r >= l)
{
int mid = (l + r) >> 1;
if(rec[mid] == val)
return mid;
else if(rec[mid] > val)
r = mid-1;
else
l = mid+1;
}
}
int main()
{
int n, d;
while(scanf("%d%d", &n, &d) != EOF)
{
int len = 1;
for(int i = 1; i <= n; i++)
{
Ri(a[i]);
rec[len++] = a[i];
}
sort(rec+1, rec+len);
int R = 2;
for(int i = 2; i < len; i++)
if(rec[i] != rec[i-1])
rec[R++] = rec[i];
sort(rec+1, rec+R);
Build(1, 1, R-1);
int ans = 0; CLR(dp, 0);
for(int i = 1; i <= n; i++)
{
// int l = lower_bound(rec+1, rec+R-1, a[i] - d) - rec;
// int r = lower_bound(rec+1, rec+R-1, a[i] + d) - rec;
// int p = lower_bound(rec+1, rec+R-1, a[i]) - rec;
int l = Findleft(a[i]-d, 1, R-1);
int r = Findright(a[i]+d, 1, R-1);
int p = Findpos(a[i], 1, R-1);
dp[i] = Query(1, l, r) + 1;
update(1, p, dp[i]);
ans = max(ans, dp[i]);
}
Pi(ans);
}
return 0;
}