#include <iostream> using namespace std; const int maxn=8000+10; struct node { int l,r,len; }tree[maxn*3]; void Create(int p,int l,int r) { tree[p].l=l; tree[p].r=r; tree[p].len=r-l+1; if(l!=r) { int mid=(l+r)/2; Create(2*p+1,l,mid); Create(2*p+2,mid+1,r); } } int find(int p,int am) { tree[p].len--; if(tree[p].l==tree[p].r) return tree[p].l; if(am<=tree[p*2+1].len) return find(p*2+1,am); else return find(p*2+2,am-tree[p*2+1].len); } int main() { int n,a[maxn],b[maxn]; while(cin>>n) { int i; Create(0,1,n); for(i=1;i<n;i++) cin>>a[i]; for(i=n-1;i>0;i--) b[i]=find(0,a[i]+1); b[0]=find(0,1); for(i=0;i<n;i++) cout<<b[i]<<endl; } return 0; }
暴力的解题思路:在最初的排列中,可以先确定最后位置i的编号:已知a[i],b[i]=a[i]+1,因为他之前的比它小的数已经是除了他之外的所有数。然后在1·n的区间中去掉已得到的数,划区间1-1,1-2,到1-n,得到后的数,在包含它 的区间中删除,对应的区间所包含的数目-1,。然后寻找从后往前的下一个数i每个区间挨着寻找,直到这个区间中1-t所包含的数正好等于a[i]+1,可得b[i]=t,用数组可实现上述算法.
以此类推,直到剩下最后一个数。再遍历每个区间,知道1~t所包含的数恰好等于1,可得最后剩下的数的编号。时间为O(n2)。
可以用线段数优化查找区间所用的时间,时间效率可优化到O(nlgn),