记住树状数组的作用,快速维护前缀和.
下面说下这题怎么做,首先得明确一点必须逆推.
最后一个数是k,那么它就是k+1小的数.且是排列,所以顺序是一定的.
下面就是说下怎么用树状数组+二分进行找到第k+1小且删除第k+1小了.其实你用树状数组只要记得它是用来快速求前缀和的就行了.
如此,我们就可以将每个位子都设为1,然后删了就表示0.然后二分出k+1即可.
代码如下:
#include <bits/stdc++.h> using namespace std; const int N=1e5+5; int a[N],b[N],sum[N],n; int lowbit(int x) { return x&(-x); } void insert(int pos,int val) { while(pos<=n) { sum[pos]+=val; pos+=lowbit(pos); } } int query(int pos) { int res=0; while(pos>0) { res+=sum[pos]; pos-=lowbit(pos); } return res; } int main() { int mid,cnt=0; cin>>n; for(int i=1;i<=n;i++) { if(i==1) a[i]=0; else cin>>a[i]; insert(i,1); } for(int i=n;i>=1;i--) { int l=1,r=n,ans=n+1; while(l<=r) { mid=(l+r)>>1; if(query(mid)>=a[i]+1) { r=mid-1; ans=min(ans,mid); } else l=mid+1; } insert(ans,-1); b[cnt++]=ans; } for(int i=cnt-1;i>=0;i--) cout<<b[i]<<endl; return 0; }