hust 1022 K-diff subsequence

题目描述

If the difference between any two adjancent elements in a sequence is not more than K, then we call this sequence is a K-diff sequence. A subsequence of some sequence is a new sequence which is formed from the original sequence by deleting some of the elements without changing the order. For example, "1 3 4 6" is a 2-diff subsequence of "1 2 3 4 5 6 7". Now give you K and a sequence whose length is N, try to find out the maximum length of the K-diff subsequence of the original sequence.

输入

The first line contains a integer T, which means there are T test cases. For each test case: The first line contains two integers: N(0 < N < 102400), K(0 <= K < 100000). The second line contains n positive integers: the orginal sequence.

输出

For each test case: Output only one line with the maximum length of the K-diff subsequence.

样例输入

2
5 2
1 3 2 2 3
5 2
1 3 4 7 2

样例输出

5
4

提示" n positive integers " 0< X <2^31

这个题很容易想到一个dp方程

dp[i]=max{dp[j]+1 | j<i, |a[j]-a[i]|<=k};

是的就是这个方程了,可是复杂度为o(n^2),这也太大了吧!但是我们在考虑一下这个方程,有一个最大值,想到线段树了吧!我们只需要维护一个区间为[a[i]-k,a[i]+k]的最大值,不就可以了吗,这个就可以了吗?不是的,看看数据吧!2^31,有那么大的数组吗?有那么大的空间吗?没有,可是有在看看n,只是10^5;这样的数组是可以开出来的,怎么开,当然是把数据离散化了,这是我的第三道再线段树上离散化求解的题目了,加油!!!

#include<map>
#include<set>
#include<stack>
#include<queue>
#include<cmath>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define  inf 0x0f0f0f0f
using namespace std;
const int maxn=200000;

struct node
{
    int left,right,nowmax;
}tree[maxn*4];
int a[maxn],b[maxn],c[maxn];

void buildtree(int c,int x,int y)
{
    tree[c].left=x;
    tree[c].right=y;
    if (x==y)
    {
        tree[c].nowmax=0;
        return;
    }
    int mid=x+(y-x)/2;
    buildtree(c*2,x,mid);
    buildtree(c*2+1,mid+1,y);
    tree[c].nowmax=max(tree[c*2+1].nowmax,tree[c*2].nowmax);
}

void insert_tree(int c,int x,int v)
{
    if (tree[c].left==x && tree[c].right==x)
    {
        tree[c].nowmax=v;
        return;
    }
    int mid=tree[c].left+(tree[c].right-tree[c].left)/2;
    if (x<=mid) insert_tree(c*2,x,v);
    else insert_tree(c*2+1,x,v);
    tree[c].nowmax=max(tree[c*2].nowmax,tree[c*2+1].nowmax);
}

int get_max(int c,int x,int y)
{
    if (tree[c].left==x && tree[c].right==y)
    {
        return tree[c].nowmax;
    }
    int mid=tree[c].left+(tree[c].right-tree[c].left)/2;
    if (y<=mid) return get_max(c*2,x,y);
    else if (x>mid) return get_max(c*2+1,x,y);
    else
    {
        return max(get_max(c*2,x,mid),get_max(c*2+1,mid+1,y));
    }
}

int find(int x,int y,int v)
{
    while (x<y)
    {
        int m=x+(y-x)/2;
        if (a[m]>=v) y=m;
        else x=m+1;
    }
    return x;
}

int unique(int n)
{
    int k=1;
    sort(b+1,b+n+1);
    a[1]=b[1];
    for (int i=2;i<=n;i++)
    if (b[i]!=b[i-1]) a[++k]=b[i];
    return k;
}

int main()
{
    int N,K,T,ans;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d",&N,&K);
        for (int i=1;i<=N;i++) {scanf("%d",&b[i]);c[i]=b[i];}
        int nown=unique(N);
        buildtree(1,1,nown);
        ans=0;
        for (int i=1;i<=N;i++)
        {
            int x=find(1,nown,c[i]-K);
            int y=find(1,nown,c[i]+K);
            if (a[y]>c[i]+K) y--;
            int temp=get_max(1,x,y)+1;
            ans=max(ans,temp);
            int id=find(1,nown,c[i]);
            insert_tree(1,id,temp);
        }
        printf("%d
",ans);
    }
    return 0;
}

作者  chensunrise

至少做到我努力了
原文地址:https://www.cnblogs.com/chensunrise/p/3748739.html