poj 2182

来源:互联网 发布:域名备案内容 编辑:程序博客网 时间:2024/05/21 11:07
#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);elsereturn 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),

 

原创粉丝点击