Restore Permutation
An array of integers p1,p2,…,pn is called a permutation if it contains each number from 1 to n exactly once. For example, the following arrays are permutations: [3,1,2],[1],[1,2,3,4,5] and [4,3,1,2]. The following arrays are not permutations: [2],[1,1],[2,3,4].
There is a hidden permutation of length n.
For each index i, you are given si, which equals to the sum of all pj such that j<i and pj<pi. In other words, si is the sum of elements before the i-th element that are smaller than the i-th element.
Your task is to restore the permutation.
Input
The first line contains a single integer n (1≤n≤2⋅105) — the size of the permutation.
The second line contains n integers s1,s2,…,sn (0≤si≤n(n−1)2).
It is guaranteed that the array s corresponds to a valid permutation of length n.
Output
Print n integers p1,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
题意:
给数组s,s(i)表示p数组中在p(i)前面的所有小于p(i)的数的和
要求恢复p数组
分析:
容易发现1肯定是在s数组中最后一个0的位置,
假设该位置为x,我们把x后面的所有数都减去1
然后2肯定是s数组中最后一个0的位置,
假设该位置为x,我们把x后面的所有数都减去2
然后3肯定是s数组中最后一个0的位置,
假设该位置为x,我们把x后面的所有数都减去3
…
操作n次之后就得到所有数的位置啦!
另外为了防止用过的0影响之后的查找,每次找到x之后,把x改为inf
code:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define int long long
//typedef long long ll;
using namespace std;
const int maxm=2e5+5;
int mi[maxm<<2];
int laz[maxm<<2];
int p[maxm];
int n;
void pushup(int node){
mi[node]=min(mi[node*2],mi[node*2+1]);
}
void pushdown(int node){
if(laz[node]){
mi[node*2]+=laz[node];
mi[node*2+1]+=laz[node];
laz[node*2]+=laz[node];
laz[node*2+1]+=laz[node];
laz[node]=0;
}
}
void build(int l,int r,int node){
if(l==r){
cin>>mi[node];
return ;
}
int mid=(l+r)/2;
build(l,mid,node*2);
build(mid+1,r,node*2+1);
pushup(node);
}
int ask(int x,int l,int r,int node){
if(l==r){
mi[node]=(1LL<<60);//改成inf
return l;
}
int mid=(l+r)/2;
pushdown(node);
int ans=1;
if(mi[node*2+1]<=x)ans=ask(x,mid+1,r,node*2+1);
else ans=ask(x,l,mid,node*2);
pushup(node);
return ans;
}
void update(int st,int ed,int val,int l,int r,int node){
if(st<=l&&ed>=r){
mi[node]+=val;
laz[node]+=val;
return ;
}
pushdown(node);
int mid=(l+r)/2;
if(st<=mid)update(st,ed,val,l,mid,node*2);
if(ed>=mid)update(st,ed,val,mid+1,r,node*2+1);
pushup(node);
}
signed main(){
ios::sync_with_stdio(0);
cin>>n;
build(1,n,1);
for(int i=1;i<=n;i++){
int x=ask(0,1,n,1);
p[x]=i;
if(x!=n){//必须加这个,否则x+1可能大于n,然后就炸了
update(x+1,n,-i,1,n,1);
}
}
for(int i=1;i<=n;i++){
cout<<p[i]<<' ';
}
cout<<endl;
return 0;
}