题目链接:https://nanti.jisuanke.com/t/41387
题目大意:对于给定序列,求出对于每个位置求出比该数大于m的最靠右的位置。
思路:首先对序列进行离散化,然后对于每个数的下标更新到线段树上,然后对于每个位置的数考虑,二分查找比该数大于m的第一个位置到最右端,查找下标的最大值即可。
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e6+7; int n,m; int w[maxn],x[maxn],Max[maxn<<2],ans[maxn]; void pushup(int rt){Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);} void update(int pos,int val,int l,int r,int rt){ if(l==r){ Max[rt]=val; return; } int mid=(l+r)>>1; if(pos<=mid) update(pos,val,l,mid,rt<<1); else update(pos,val,mid+1,r,rt<<1|1); pushup(rt); } int query(int L,int R,int l,int r,int rt){ if(L<=l&&R>=r){ return Max[rt]; } int ans=0,mid=(l+r)>>1; if(mid>=L) ans=max(ans,query(L,R,l,mid,rt<<1)); if(mid<=R) ans=max(ans,query(L,R,mid+1,r,rt<<1|1)); return ans; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&w[i]); x[i]=w[i]; } sort(x+1,x+n+1); int len=unique(x+1,x+1+n)-x-1; for(int i=1;i<=n;i++){ int pos=lower_bound(x+1,x+1+len,w[i])-x; update(pos,i,1,len,1); } for(int i=1;i<=n;i++){ int pos=lower_bound(x+1,x+1+len,w[i]+m)-x; ans[i]=query(pos,len,1,len,1)-i-1;; if(ans[i]<0)ans[i]=-1; } printf("%d",ans[1]); for(int i=2;i<=n;i++) printf(" %d",ans[i]); printf(" "); return 0; }