D. Restore Permutation
題意:第一行給你一個數n,第二行輸入n個數,第 i 個數表示其前面的所有比其小的數的和,讓你還原這個原數列(該原數列數值1->n)。
思路:從後往前解決。利用樹狀數組求出tree[i]。利用二分查找a[i],確定位置,存入s[i],最後輸出。
代碼:
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll tree[N],n;
ll a[N],s[N];
ll lowbit(ll k)
{
return k&(-k);
}
void add(ll k,ll num)
{
while(k<=n)
{
tree[k]+=num;
k+=lowbit(k);
}
}
ll read(ll k)
{
ll sum=0;
while(k)
{
sum+=tree[k];
k-=lowbit(k);
}
return sum;
}
ll tao(ll x)
{
ll ret=-1;
ll l=1,r=n,mid;
while(l<=r)
{
mid=(l+r)>>1;
ll ans=read(mid-1);
if(ans<=x)
{
l=mid+1;
ret=mid;
}
else
r=mid-1;
}
add(ret,-ret);
return ret;
}
int main()
{
scanf("%lld",&n);
for(ll i=1;i<=n;i++)
{
add(i,i);
}
for(ll i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
for(int i=n;i>=1;i--)
{
s[i]=tao(a[i]);
}
for(int i=1;i<=n;i++)
printf("%lld ",s[i]);
return 0;
}