csu 1555(线段树经典插队模型-根据逆序数还原序列)

1555: Inversion Sequence

Time Limit: 2 Sec  Memory Limit: 256 MB
Submit: 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;
}

 

posted @ 2016-08-21 20:21  樱花庄的龙之介大人  阅读(449)  评论(0编辑  收藏  举报