Restore Permutation CodeForces - 1208D

An array of integers p1,p2,…,pnp1,p2,…,pn is called a permutation if it contains each number from 11 to nn exactly once. For example, the following arrays are permutations: [3,1,2],[1],[1,2,3,4,5][3,1,2],[1],[1,2,3,4,5] and [4,3,1,2][4,3,1,2]. The following arrays are not permutations: [2],[1,1],[2,3,4][2],[1,1],[2,3,4].

There is a hidden permutation of length nn.

For each index ii, you are given sisi, which equals to the sum of all pjpj such that j<ij<iand pj<pipj<pi. In other words, sisi is the sum of elements before the ii-th element that are smaller than the ii-th element.

Your task is to restore the permutation.

Input

The first line contains a single integer nn (1≤n≤2⋅1051≤n≤2⋅105) — the size of the permutation.

The second line contains nn integers s1,s2,…,sns1,s2,…,sn (0≤si≤n(n−1)20≤si≤n(n−1)2).

It is guaranteed that the array ss corresponds to a valid permutation of length nn.

Output

Print nn integers p1,p2,…,pnp1,p2,…,pn — the elements of the restored permutation. We can show that the answer is always unique.

Examples

Input

3
0 0 0

Output

3 2 1

Input

2
0 1

Output

1 2

Input

5
0 1 1 1 10

Output

1 4 3 2 5

Note

In the first example for each ii there is no index jj satisfying both conditions, hence sisi are always 00.

In the second example for i=2i=2 it happens that j=1j=1 satisfies the conditions, so s2=p1s2=p1.

In the third example for i=2,3,4i=2,3,4 only j=1j=1 satisfies the conditions, so s2=s3=s4=1s2=s3=s4=1. For i=5i=5 all j=1,2,3,4j=1,2,3,4 are possible, so s5=p1+p2+p3+p4=10s5=p1+p2+p3+p4=10.

一开始p中最右边的0的位置对应着原序列中的1,我们确定了1的位置,将1后面的每个数减1,p中最右边的0的位置就对应着原序列中的2,我们就能确定原序列中2的位置,以此类推我们就能得出整个原序列。用数据结构维护一下区间最小值和区间更新就行了。

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#include<iostream>
#include<time.h>
using namespace std;
typedef long long slong;
const int maxn=200005;
const double exc=1e-7;
const long long inf=1e15;
int ans[maxn];
struct value
{
    long long val;
    int index;
};
struct point
{
    long long f;
    value w;
}tree[maxn<<2];
int cnt;
void up(int k)
{
    if(tree[k*2].w.val<tree[k*2+1].w.val)
        tree[k].w=tree[k*2].w;
    else tree[k].w=tree[k*2+1].w;
}
void build(int l,int r,int k)
{
    tree[k].f=0;
    tree[k].w.val=inf;
    if(l==r)
    {
        tree[k].w.index=++cnt;
        scanf("%lld",&tree[k].w.val);
        return;
    }
    int bet=(l+r)/2;
    build(l,bet,k*2);
    build(bet+1,r,k*2+1);
    up(k);
}
void down(int k)
{
    tree[k*2].w.val-=tree[k].f;
    tree[k*2+1].w.val-=tree[k].f;
    tree[k*2].f+=tree[k].f;
    tree[k*2+1].f+=tree[k].f;
    tree[k].f=0;
}
void change(int l,int r,int k,long long val,int ll,int rr)
{
    if(ll<=l&&rr>=r)
    {
        tree[k].w.val-=val;
        tree[k].f+=val;
        return;
    }
    if(tree[k].f) down(k);
    int bet=(l+r)/2;
    if(ll<=bet) change(l,bet,k*2,val,ll,rr);
    if(rr>bet) change(bet+1,r,k*2+1,val,ll,rr);
    up(k);
}
void pointchange(int l,int r,int k,long long val,int poi)
{
    if(l==r)
    {
        tree[k].w.val=val;
        return;
    }
    if(tree[k].f) down(k);
    int bet=(l+r)/2;
    if(poi<=bet) pointchange(l,bet,k*2,val,poi);
    else pointchange(bet+1,r,k*2+1,val,poi);
    up(k);
}
int main()
{
    int n;
    scanf("%d",&n);
    build(1,n,1);
    for(int i=1;i<=n;i++)
    {
        value a=tree[1].w;
        ans[a.index]=i;
        pointchange(1,n,1,inf,a.index);
        change(1,n,1,i,a.index,n);
    }
    for(int i=1;i<=n;i++)
        printf("%d ",ans[i]);
    printf("\n");
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值