题意:给定一个排列和数组b[i]表示i前面比a[i]小的点的个数,
求a[i](n的一个排列)
solution:维护一个c数组,表示c[]={1,2,……,n}。从右向左对每个b[i],
找到最小的j 使c[j]=b[i].则a[i]=j;
如何维护c->树状数组
如何查找j->二分
求a[i](n的一个排列)
solution:维护一个c数组,表示c[]={1,2,……,n}。从右向左对每个b[i],
找到最小的j 使c[j]=b[i].则a[i]=j;
如何维护c->树状数组
如何查找j->二分
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
#define N 200005
int n;
int a[N];
struct bit{
int c[N];
void clear(){memset(c,0,sizeof(c));}
int lowbit(int x) {return x&(-x);}
void update(int x,int y)
{ while (x<N)
{ c[x]+=y;
x+=lowbit(x);
}
}
int query(int x)
{ int re=0;
while (x)
{ re+=c[x];
x-=lowbit(x);
}
return re;
}
}bit;
int find(int p)
{
int l=1,r=n,ans,mid;
while (r>=l)
{
int mid=(l+r)>>1;
if (bit.query(mid)>=p){ans=mid; r=mid-1;}
else l=mid+1;
}
return ans;
}
void doit()
{ bit.clear();
scanf("%d",&n);
for (int i=1;i<=n;i++)
{scanf("%d",&a[i]);
bit.update(i,1);
}
for (int i=n;i>=1;i--)
{a[i]=find(i-a[i]);
bit.update(a[i],-1);
}
printf("%d",a[1]);
for (int i=2;i<=n;i++)
printf(" %d",a[i]);
printf("\n");
}
int main()
{ int cas;
scanf("%d",&cas);
while (cas--) doit();
return 0;
}