题目链接:
http://poj.org/problem?id=2182
题目意思:
已知1~n组成的一个序列中每个数的顺序数(也就是告诉前面有几个小于他的数),求该序列。
解题思路:
如果从后往前考虑,并且计算完后就把后面的去掉,当前的顺序数,也即是该数在去掉后面数后的序列中的大小位置。
在一个序列中查找第几大的数可以借用线段树来做。
区间维护的是【l,r】间有还剩有多少个数。每次找到后就把该数给去掉。
代码:
//#include<CSpreadSheet.h> #include<iostream> #include<cmath> #include<cstdio> #include<sstream> #include<cstdlib> #include<string> #include<string.h> #include<cstring> #include<algorithm> #include<vector> #include<map> #include<set> #include<stack> #include<list> #include<queue> #include<ctime> #include<bitset> #define eps 1e-6 #define INF 0x3f3f3f3f #define PI acos(-1.0) #define ll __int64 #define LL long long #define lson l,m,(rt<<1) #define rson m+1,r,(rt<<1)|1 #define M 1000000007 #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; #define Maxn 8100 struct Node { int va; }node[Maxn<<2]; int n,ans[Maxn],save[Maxn]; void pushup(int rt) //向上更新 { node[rt].va=node[rt<<1].va+node[(rt<<1)|1].va; } void build(int l,int r,int rt) { if(l==r) //树根 { node[rt].va=1; return ; } int m=(l+r)>>1; build(lson); build(rson); pushup(rt); } void solve(int l,int r,int rt,int va,int nn) { if(l==r) //找到喽 { ans[nn]=l; //更新该值 node[rt].va--; //该区间剩余数减掉 return ; } int m=(l+r)>>1; if(va<=node[rt<<1].va) //先左后有 如果左区间能够满足 solve(lson,va,nn); else solve(rson,va-node[rt<<1].va,nn); //找右区间 pushup(rt); } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); while(~scanf("%d",&n)) { build(1,n,1); for(int i=2;i<=n;i++) scanf("%d",&save[i]); for(int i=n;i>=2;i--) solve(1,n,1,save[i]+1,i); solve(1,n,1,1,1); for(int i=1;i<=n;i++) printf("%d\n",ans[i]); } return 0; }