#include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<ctype.h> #include<math.h> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);} #define MS(x,y) memset(x,y,sizeof(x)) #define MC(x,y) memcpy(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) #define ls o<<1 #define rs o<<1|1 typedef long long LL; typedef unsigned long long UL; typedef unsigned int UI; template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;} template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;} const int N=1e5+10,Z=1e9+7,ms63=1061109567; int n,k; LL a[N],b[N]; int pre[N]; int O,V,P,Pre; struct C { int l,r; int v,p; }c[1<<18]; void build(int o,int l,int r) { c[o].l=l; c[o].r=r; c[o].v=0; c[o].p=0; if(l==r)return; int m=(l+r)>>1; build(ls,l,m); build(rs,m+1,r); } void pushup(int o) { if(c[ls].v>=c[rs].v) { c[o].v=c[ls].v; c[o].p=c[ls].p; } else { c[o].v=c[rs].v; c[o].p=c[rs].p; } } void update(int o,int l,int r) { if(c[o].v<=V)return; if(c[o].l==l&&c[o].r==r) { V=c[o].v; Pre=c[o].p; return; } int m=(c[o].l+c[o].r)>>1; if(r<=m)update(ls,l,r); else if(l>m)update(rs,l,r); else { update(ls,l,m); update(rs,m+1,r); } } void modify(int o) { if(c[o].l==c[o].r) { c[o].v=V; c[o].p=P; return; } int m=(c[o].l+c[o].r)>>1; O<=m?modify(ls):modify(rs); pushup(o); } void print(int p) { if(pre[p])print(pre[p]); printf("%d ",p); } int main() { while(~scanf("%d%d",&n,&k)) { for(int i=1;i<=n;++i) { scanf("%lld",&a[i]); b[i]=a[i]; } sort(b+1,b+n+1); int m=unique(b+1,b+n+1)-b-1; build(1,1,m); int ansv=0; int ansp; for(int i=1;i<=n;++i) { int l=upper_bound(b+1,b+m+1,a[i]-k)-1-b; int r=lower_bound(b+1,b+m+1,a[i]+k)-b; V=0;Pre=0; if(1<=l)update(1,1,l); if(r<=m)update(1,r,m); ++V;pre[i]=Pre; if(V>ansv){ansv=V;ansp=i;} O=lower_bound(b+1,b+m+1,a[i])-b;P=i; modify(1); } printf("%d\n",ansv); print(ansp);puts(""); } return 0; } /* 【trick&&吐槽】 线段树已经是我的压箱底了,23333 【题意】 给你一个长度为n的数列。 每个数的数值都在[1,1e15]范围。 我们想找到最大长度的数列,使得该数列相邻两个数的绝对值之差都至少为d(0<=d<=1e9) 【类型】 离散化线段树 【分析】 首先这题是很难贪心的。 于是我们要想办法利用数据结构维护。 每个数的前驱,下标在它之前,这个是很好保证的。 然而,并非就是在前驱中,选择一个权值最大的前驱。 我们还有其他限制条件,就是两者的绝对值之差至少为k。 如何保证这个呢? 我们从"恰好"开始找突破。 对于一个数,有恰好比它小k的数,有恰好比它大k的数。 这个范围内的前驱我们是不能取的,除此之外的数我们都能取。 这些数的数值比较分散。 我们该怎么办?离散化! 这里具体而言有两种做法—— 做法一,是把每个数恰好小k和恰好大k的数,都插入线段树。 这么我们就知道,对于每个数,它能取哪些区间段的数作为它的前驱了。 然而这个做法会使得空间扩大为三倍。 我们能不能不插入这两个特殊点呢? 不插入的话,我们对于[x-k,x+k]的区间段, 第一个左区间段合法的数就是upper_bound(x-k)-1 第一个右区间段外合法的数就是lower_bound(x+k) 我们只要从这2个区间段更新出最大权值的前驱即可。 然后还有一个需要处理的问题,就是我们还要输出路径。 这个要如何实现呢?我们在更新区间最大值的同时,同时更新位点(这个位点是基于原始数组下标的)就好啦。 【时间复杂度&&优化】 O(nlogn) */