题意:给定一个数组和一个k值,要求生成一个新数组,新数组满足每个元素都来自原数组(不一定连续,但顺序不能变),并且相邻数组的差值不能超过k。问新数组最长的长度是多少
思路:从原数组的任何一个元素开始往后找都能生成一个新的数组B,所以要找出全部的B来比较长度,这里涉及到相邻元素差值不超过k,所以限制了区间相邻值的范围,往后找就是更改区间,想到单点修改和区间查询
#include<iostream> 线段树 单点修改区间查询
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=3e5+10;
const ll mod=998244353;
int n,a[maxn],c[maxn],k,i;
struct node{
int l,r;
int v;
}tree[maxn<<2];
void update(int k)
{
tree[k].v=max(tree[k<<1].v,tree[k<<1|1].v);
}
void build(int k,int l,int r)
{
tree[k].l=l,tree[k].r=r,tree[k].v=0;
if(l==r)
return ;
int mid=(l+r)/2;
build(k<<1,l,mid),build(k<<1|1,mid+1,r);
}
void modify(int k,int pos,int v)
{
if(tree[k].l==tree[k].r)
{
tree[k].v=max(tree[k].v,v);
return;
}
int mid=(tree[k].l+tree[k].r)/2;
if(pos<=mid)
modify(k<<1,pos,v);
else
modify(k<<1|1,pos,v);
update(k);
}
int query(int l, int r, int k)
{
if (l<=tree[k].l && r>=tree[k].r){
return tree[k].v;
}
int mid=(tree[k].l+tree[k].r)/2;
int v=0;
if(l<=mid)
v=max(v,query(l,r,k<<1));
if(r>mid)
v=max(v,query(l,r,k<<1|1));
return v;
}
int main()
{
cin>>n>>k;
for( i=1;i<=n;i++)
{
cin>>a[i];
}
build(1,0,300000);
int res=0;
for(i=1;i<=n;i++)
{
int l=max(0,a[i]-k),r=min(300000,a[i]+k);
c[i]=1+query(l,r,1);
modify(1,a[i],c[i]);
res=max(res,c[i]);
}
cout<<res<<endl;
return 0;
}