1555: Inversion Sequence
Time Limit: 2 Sec Memory Limit: 256 MBSubmit: 469 Solved: 167
[Submit][Status][Web Board]
Description
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”.
Input
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.
Output
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”.
Sample Input
5
1 2 0 1 0
3
0 0 0
2
1 1
Sample Output
3 1 5 2 4
1 2 3
No solution
HINT
题意:知道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; }