题意
有n个柱子,每个柱子有一个高度
hi
h
i
,每个柱子可以跳到它后面高度与它相差大于d的柱子(即
|hi−hj|≥d
|
h
i
−
h
j
|
≥
d
)
求最多可以跳多少个柱子
题解
ansi=max(ansj+1)(|hi−hj|>=d且j<i)
a
n
s
i
=
m
a
x
(
a
n
s
j
+
1
)
(
|
h
i
−
h
j
|
>=
d
且
j
<
i
)
因此建立一棵线段树,节点表示高度为i的点
每次查询到一个数,
ansi
a
n
s
i
等于1~
hi−d
h
i
−
d
和
hi+d
h
i
+
d
中最大数的最大值+1
线段树维护最大值和最大值是哪个点
代码
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 110000
long long a[N],b[N],d,ans[N];
int h1[N],h2[N],n,m,h[N],mx=0,data[N],tot=0;
struct node{int l,r,pos;long long mx;}tree[4*N];
void build(int v,int l,int r){
tree[v].l=l;tree[v].r=r;tree[v].mx=0;
if(l==r) return;int mid=l+r>>1;
build(v<<1,l,mid);build(v<<1|1,mid+1,r);
}
int query(int v,int l,int r){
if(l<=tree[v].l && tree[v].r<=r) return tree[v].pos;
int mid=tree[v].l+tree[v].r>>1;int ans1=0,ans2=0;
if(l<=mid) ans1=query(v<<1,l,r);
if(mid<r) ans2=query(v<<1|1,l,r);
if(tree[ans1].mx>=tree[ans2].mx) return ans1;
else return ans2;
}
void update(int v){
tree[v].mx=max(tree[v<<1].mx,tree[v<<1|1].mx);
if(tree[v<<1].mx>=tree[v<<1|1].mx) tree[v].mx=tree[v<<1].mx,tree[v].pos=tree[v<<1].pos;
else tree[v].mx=tree[v<<1|1].mx,tree[v].pos=tree[v<<1|1].pos;
}
void add(int v,int l,long long x){
if(l==tree[v].l && l==tree[v].r){tree[v].mx=x;tree[v].pos=v;return;}
int mid=tree[v].l+tree[v].r>>1;
if(l<=mid) add(v<<1,l,x);
if(mid<l) add(v<<1|1,l,x);
update(v);
}
int main(){
scanf("%d%d",&n,&d);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),b[i]=a[i];a[n+1]=b[n+1]=(long long)1000000000000001;
sort(b+1,b+n+2);m=unique(b+1,b+n+2)-b-1;
for(int i=1;i<=m-1;i++){
h1[i]=upper_bound(b+1,b+m+1,b[i]-d)-b-1;
h2[i]=lower_bound(b+1,b+m+1,b[i]+d)-b;
}
build(1,1,m-1);
for(int i=1;i<=n;i++){
a[i]=lower_bound(b+1,b+m+1,a[i])-b;int y=0,z=0;
if(h1[a[i]]) y=query(1,1,h1[a[i]]);
if(h2[a[i]]<m) z=query(1,h2[a[i]],m-1);
if(tree[y].mx>=tree[z].mx) h[i]=tree[y].l,ans[i]=tree[y].mx+1;
else h[i]=tree[z].l,ans[i]=tree[z].mx+1;
add(1,a[i],ans[i]);
if(ans[i]>ans[mx]) mx=i;
}printf("%d\n",ans[mx]);
int t=h[mx];data[++tot]=mx;
for(int i=mx-1;i>=1;i--){
if(a[i]==t){
data[++tot]=i;
t=h[i];
if(!t)break;
}
}
for(int i=tot;i>=1;i--) printf("%d ",data[i]);
return 0;
}