目录:
题目:
分析:
需要用树状数组维护
01
01
序列前缀和,并且查找某个位置的前缀和是
k
k
,也就是前面有个
1
1
这个可以用二分,是,但是用倍增就是
O(logn)
O
(
l
o
g
n
)
不得不说树状数组和倍增的相性真的很好,倍增到的节点维护信息与上一级完全没有重合
譬如说跳
8
8
可以跳到,跳
4
4
的时候如果可以跳直接加上
c[12]
c
[
12
]
就可以,因为
c[12]
c
[
12
]
维护的是
c[9]
c
[
9
]
到
c[12]
c
[
12
]
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#define LL long long
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
int min(int x,int y)
{ return x<y? x:y; }
int max(int x,int y)
{ return x>y? x:y; }
int c[100001];
int n=read();
void add(int x,int y)
{
for(;x<=n;x+=x&-x) c[x]+=y;
return;
}
int h[100001];int a[100001];
int main()
{
add(1,1);
for(int i=2;i<=n;i++)
a[i]=read(),add(i,1);
int log_233=(int)log2(n);
for(int i=n;i>=1;i--)
{
int ans=0,sum=0;
for(int p=log_233;p>=0;p--)
{
if(ans+(1<<p)<=n&&sum+c[ans+(1<<p)]<=a[i])
sum+=c[ans+(1<<p)],ans+=(1<<p);
}
h[i]=ans+1;
add(ans+1,-1);
}
for(int i=1;i<=n;i++) printf("%d\n",h[i]);
return 0;
}