For
sequence i1, i2, i3, … , iN, we set aj to be the number of members in
the sequence which are prior to j and greater to j at the same time. The
sequence a1, a2, a3, … , aN is referred to as the inversion sequence of
the original sequence (i1, i2, i3, … , iN). For example, sequence 1, 2,
0, 1, 0 is the inversion sequence of sequence 3, 1, 5, 2, 4. Your task
is to find a full permutation of 1~N that is an original sequence of a
given inversion sequence. If there is no permutation meets the
conditions please output “No solution”.
There are several test cases.
Each test case contains 1 positive integers N in the first line.(1 ≤ N ≤ 10000).
Followed in the next line is an inversion sequence a1, a2, a3, … , aN (0 ≤ aj < N)
The input will finish with the end of file.
For each case,
please output the permutation of 1~N in one line. If there is no
permutation meets the conditions, please output “No solution”.
题意:知道1-n 所有数的逆序数,要求还原序列.例如 : 1 2 0 1 0 ,那么 1 前面有 1个数大于1,2前面有 2个数大于2,依次类推.
不会的可以去做一下poj 2828 ,经典模型了,在线段树更新的时候就能够完成所有操作了.对于某个数 i ,它前面的数数量为 k ,那么它就在线段树第 k+1 个空位上.假设当前的线段树能够插的空位数量不足 k+1 ,那么就无解了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define N 10005
int a[N],ans[N];
int tree[N<<2];
void pushup(int idx){
tree[idx] = tree[idx<<1]+tree[idx<<1|1];
}
void build(int l,int r,int idx){
if(l==r){
tree[idx] = 1;
return;
}
int mid = (l+r)>>1;
build(l,mid,idx<<1);
build(mid+1,r,idx<<1|1);
pushup(idx);
}
void update(int value,int i,int l,int r,int idx){
if(l==r){
ans[l] = i;
tree[idx] = 0;
return;
}
int mid = (l+r)>>1;
if(tree[idx<<1]>=value) update(value,i,l,mid,idx<<1); ///插向左子树
else update(value-tree[idx<<1],i,mid+1,r,idx<<1|1);
pushup(idx);
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF){
memset(tree,0,sizeof(tree));
memset(ans,0,sizeof(ans));
build(1,n,1);
bool flag = false;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
a[i]++; ///它前面的空格数为a[i] ,自然它应该在第 a[i]+1 个空格位置
if(tree[1]<a[i]) flag = true;
if(!flag)
update(a[i],i,1,n,1);
}
if(flag){
printf("No solution\n");
continue;
}
for(int i=1;i<n;i++){
printf("%d ",ans[i]);
}
printf("%d\n",ans[n]);
}
return 0;
}