题目链接:https://nanti.jisuanke.com/t/41387
按wi的值建立权值线段树维护值为wi出现的最后位置,对于第i个人的答案,查询线段树[wi+m,max]区间的最大位置pos,令如果pos-i-1小于等于-1则是在i之后不存在大于等于wi+m的人,否则第i个人的答案即为pos-i-1。由于wi范围过大所以需对wi离散化
#include<iostream> #include<cmath> #include<algorithm> using namespace std; #define ll long long #define ls l,mid,rt<<1 #define rs mid+1,r,rt<<1|1 #define maxn 1000010 int n,m,mx[maxn<<2]; ll w[maxn],x[maxn],li[maxn],ans[maxn]; void pushup(int rt) { mx[rt]=max(mx[rt<<1],mx[rt<<1|1]); } void update(int L,int c,int l,int r,int rt) { if(l==r) { mx[rt]=c; return ; } int mid=l+r>>1; if(L<=mid)update(L,c,ls); else update(L,c,rs); pushup(rt); } int query(int L,int R,int c,int l,int r,int rt) { if(L<=l&&R>=r) { return mx[rt]; } int mid=l+r>>1,ret=0; if(L<=mid)ret=max(ret,query(L,R,c,ls)); if(R>mid)ret=max(ret,query(L,R,c,rs)); return ret; } int main() { scanf("%d%d",&n,&m); int tot=0; for(int i=1;i<=n;i++) { scanf("%lld",&w[i]); x[++tot]=w[i]; x[++tot]=w[i]+m; } sort(x+1,x+1+tot); int nx=unique(x+1,x+1+tot)-x-1; int L; for(int i=1;i<=n;i++) { L=lower_bound(x+1,x+1+nx,w[i])-x; update(L,i,1,nx,1); } for(int i=1;i<=n;i++) { L=lower_bound(x+1,x+1+nx,w[i]+m)-x; L=query(L,nx,i,1,nx,1); if(L==-1)ans[i]=-1; else ans[i]=L-i-1; if(ans[i]<-1)ans[i]=-1; } for(int i=1;i<n;i++) printf("%lld ",ans[i]); printf("%lld ",ans[n]); return 0; }