原题链接:E - Smooth Subsequence (atcoder.jp)
题目翻译:给你一个长度为n的序列a=(a1,a2,…,an)。求长度为a子序列的最大长度,使得任意两个相邻项之间的绝对差最多为D。序列A的子序列是指从a中删除0个或多个元素,并将其余元素按原来的顺序排列后得到的序列。
n的范围是[1,5e5],D的范围是[0,5e5],A中元素的范围是[1,5e5]。
思路:可以开一个从1到5e5的线段树,然后去查询[a[i]-D,a[i]+D]的范围内的数求最大值,并且将最大值更新到a[i]的位置。
#pragma GCC optimize(2)
#include
#define endl '\n'
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair pii;
const int N=1e6+10;
ll p[N<<2],f[N<<2],MAX=5e5+10;
ll query(ll l,ll r,ll pl,ll pr,ll k)
{
if(pl<=l&&r<=pr)
{
return f[k];
}
ll mid=l+r>>1;
ll max1=0;
if(pl<=mid)max1=max(max1,query(l,mid,pl,pr,k<<1));
if(pr>mid)max1=max(max1,query(mid+1,r,pl,pr,k<<1|1));
return max1;
}
void update(ll l,ll r,ll pos,ll k,ll v)
{
if(l==r)
{
f[k]=max(f[k],v);
return;
}
ll mid=l+r>>1;
if(pos<=mid)update(l,mid,pos,k<<1,v);
else update(mid+1,r,pos,k<<1|1,v);
f[k]=max(f[k<<1],f[k<<1|1]);
}
int main()
{
ios::sync_with_stdio(NULL);
cin.tie(0),cout.tie(0);
ll n,m;cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>p[i];
}
for(int i=1;i<=n;i++)
{
ll k=query(1,MAX,max(1ll,p[i]-m),min(MAX,p[i]+m),1)+1;
update(1,MAX,p[i],1,k);
for(int i=1;i<=100;i++)
{
cout<