在第i个木桩,想跳到第j个木桩,需要满足条件:i<j 同时 |hi-hj|>=d
现在BSNY希望能跳的木桩数量最多,问最多可以跳多少木桩?
思路:找到一条最长的序列,和求最长上升子序列差不多,每一次找前面的最大值n^2会t掉,可以用线段树维护一段高度中的最大值和它对应的下标,h离散化一下。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 10000000
#define pi acos(-1.0)
#define eps 1e-8
#define seed 131
using namespace std;
typedef pair<int,int> pii;
typedef unsigned long long ULL;
typedef long long LL;
const int maxn=100005;
int n,d;
LL h[maxn];
LL hh[maxn*3];
int lr[maxn][2];
int dp[maxn];
int pre[maxn];
struct Node
{
int w;
int id;
Node():w(0),id(-1){}
}node[(maxn*3)<<2];
void pushup(int l,int r,int rt)
{
if(node[rt<<1].w>=node[rt<<1|1].w)
{
node[rt].w=node[rt<<1].w;
node[rt].id=node[rt<<1].id;
}
else
{
node[rt].w=node[rt<<1|1].w;
node[rt].id=node[rt<<1|1].id;
}
}
void update(int L,int R,int ww,int o,int l,int r,int rt)
{
if(L<=l&&R>=r)
{
node[rt].w=ww;
node[rt].id=o;
return;
}
int m=(l+r)>>1;
if(L<=m)
update(L,R,ww,o,l,m,rt<<1);
if(R>m)
update(L,R,ww,o,m+1,r,rt<<1|1);
pushup(l,r,rt);
}
Node query(int L,int R,int l,int r,int rt)
{
Node u;
if(L<=l&&R>=r)
{
u.w=node[rt].w;
u.id=node[rt].id;
return u;
}
int m=(l+r)>>1;
if(L<=m)
{
Node p=query(L,R,l,m,rt<<1);
if(p.w>u.w)
{
u.w=p.w;
u.id=p.id;
}
}
if(R>m)
{
Node p=query(L,R,m+1,r,rt<<1|1);
if(p.w>u.w)
{
u.w=p.w;
u.id=p.id;
}
}
return u;
}
void dfs(int cnt)
{
if(cnt==-1)
return;
dfs(pre[cnt]);
printf("%d ",cnt+1);
}
int main()
{
scanf("%d%d",&n,&d);
int e=0;
for(int i=0;i<n;i++)
{
cin>>h[i];
hh[e++]=h[i];
hh[e++]=h[i]-d;
hh[e++]=h[i]+d;
}
sort(hh,hh+e);
int k=unique(hh,hh+e)-hh;
for(int i=0;i<n;i++)
{
LL u=h[i];
h[i]=lower_bound(hh,hh+k,u)-hh;
lr[i][0]=lower_bound(hh,hh+k,u-d)-hh;
lr[i][1]=lower_bound(hh,hh+k,u+d)-hh;
}
dp[0]=1;
pre[0]=-1;
update(h[0],h[0],1,0,0,maxn*3,1);
int op=0;
int mx=1;
for(int i=1;i<n;i++)
{
Node p=query(0,lr[i][0],0,maxn*3,1);
if(p.id==-1)
{
dp[i]=1;
pre[i]=-1;
}
else
{
dp[i]=p.w+1;
pre[i]=p.id;
}
p=query(lr[i][1],maxn*3,0,maxn*3,1);
if(p.id!=-1)
{
if(dp[i]<p.w+1)
{
dp[i]=p.w+1;
pre[i]=p.id;
}
}
if(dp[i]>mx)
{
mx=dp[i];
op=i;
}
update(h[i],h[i],dp[i],i,0,maxn*3,1);
}
printf("%d\n",mx);
dfs(op);
return 0;
}