题目:http://poj.org/problem?id=2182
从后往前确定,自己位置之前没有被确定的且比自己编号小的个数+1即为自己的编号;
利用树状数组快速查找,可另外开一个b数组,角标为编号大小,而其值为是否使用,二分查找到恰好满足条件的位置,向后一直找到没被用过的第一个编号即为此位置编号。
代码如下:
#include<iostream> #include<cstdio> using namespace std; int n,a[8005],f[8005],ans[8005]; bool b[8005]; int query(int x) { int sum=0; for(;x;x-=x&-x) sum+=f[x]; return sum; } void add(int x,int y) { for(;x<=n;x+=(x&-x)) f[x]+=y; } int main() { scanf("%d",&n); f[1]=1;//! for(int i=2;i<=n;i++) { scanf("%d",&a[i]); f[i]=i&-i; } for(int i=n;i>=1;i--) { int l=1,r=n; while(l<=r) { int mid=(l+r)/2; int k=query(mid-1); if(a[i]>k)l=mid+1; if(a[i]<k)r=mid-1; if(a[i]==k) { while(b[mid])mid++; ans[i]=mid; b[mid]=1; add(mid,-1); break; } } } for(int i=1;i<=n;i++) printf("%d\n",ans[i]); return 0; }