题目链接
题目大意
每次将数字 i i i 插入到 A A A 的第 P i P_i Pi 个位置,输出操作结束后的数组 A A A。
思路分析
对于数字 i i i,若倒序操作,则所有的空位即为正序操作中已经填了的数字,非空位为还未填的数字,所以应将其插入第 P i P_i Pi 个空位。我们可以用线段树维护区间 [ l , r ] \left[l,r\right] [l,r] 中空位的个数,单次查询复杂度 O ( log n ) O(\log{n}) O(logn),总时间复杂度为 O ( n log n ) O(n\log{n}) O(nlogn)。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int n;
int p[N],tree[N*4],a[N];
inline void push_up(int x){
tree[x]=tree[x*2]+tree[x*2+1];
}
void build(int l,int r,int x){
if (l==r){
tree[x]=1;
return;
}
int mid=(l+r)/2;
build(l,mid,x*2);
build(mid+1,r,x*2+1);
push_up(x);
}
int binary(int l,int r,int x,int cnt){//线段树二分
if (l==r){
tree[x]=0;
return l;
}
int mid=(l+r)/2,ans=0;
if (cnt<=tree[x*2]) ans=binary(l,mid,x*2,cnt);
else ans=binary(mid+1,r,x*2+1,cnt-tree[x*2]);
push_up(x);
return ans;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;++i) scanf("%d",p+i);
build(1,n,1);//建树
for (int i=n;i>=1;--i) a[binary(1,n,1,p[i])]=i;
for (int i=1;i<=n;++i) printf("%d ",a[i]);
return 0;
}