D. Restore Permutation
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
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<i and 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
Copy
3 0 0 0
output
Copy
3 2 1
input
Copy
2 0 1
output
Copy
1 2
input
Copy
5 0 1 1 1 10
output
Copy
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.
对应i给出一个数si,代表<i且比ai小的和值。求这个序列。
从大到小二分答案,靠近n的位置放的尽量大。
用树状数组计算>mid-1的和值,然后二分判断。
#include <algorithm> //STL通用算法
#include <bitset> //STL位集容器
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex> //复数类
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque> //STL双端队列容器
#include <exception> //异常处理类
#include <fstream>
#include <functional> //STL定义运算函数(代替运算符)
#include <limits>
#include <list> //STL线性列表容器
#include <map> //STL 映射容器
#include <iomanip>
#include <ios> //基本输入/输出支持
#include<iosfwd> //输入/输出系统使用的前置声明
#include <iostream>
#include <istream> //基本输入流
#include <ostream> //基本输出流
#include <queue> //STL队列容器
#include <set> //STL 集合容器
#include <sstream> //基于字符串的流
#include <stack> //STL堆栈容器
#include <stdexcept> //标准异常类
#include <streambuf> //底层输入/输出支持
#include <string> //字符串类
#include <utility> //STL通用模板类
#include <vector> //STL动态数组容器
#include <cwchar>
#include <cwctype>
#define ll long long
using namespace std;
//priority_queue<int,vector<int>,less<int> >q;
int dx[]= {-1,1,0,0,-1,-1,1,1};
int dy[]= {0,0,-1,1,-1,1,1,-1};
const int maxn = 200000+66;
const ll mod=998244353;
const int inf=999999;
int n;
ll s[maxn];
ll c[maxn];
ll ans[maxn];
ll lowbit(ll x)
{
return x&(-x);
}
ll query(ll x)
{
ll ans=0;
while(x>0)
{
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
void update(ll x,ll v)
{
while(x<=n)
{
c[x]+=v;
x+=lowbit(x);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&s[i]);
update(i,i);
}
for(int i=n;i>=1;i--)
{
ll l=1,r=n,mid;
while(l<r)
{
mid=(l+r+1)/2;
if(query(mid-1)<=s[i])
{
l=mid;
}else
{
r=mid-1;
}
}
ans[i]=l;
update(l,-l);
}
for(int i=1;i<=n;i++)
{
if(i!=n)printf("%I64d ",ans[i]);
else printf("%I64d\n",ans[i]);
}
}