问题 B: Number
时间限制: 1 Sec 内存限制: 256 MB题目描述
一个排列,求出了 a 数组,其中 ai 表示第 i 个数左边有多少个数比它小
计算出原来的排列
输入
第一行输入 n 接下来 n - 1 个整数 ai,下标从 2 开始
输出
输出 n 个整数表示原排列
样例输入
51210
样例输出
24531
提示
对于 20% 的数据满足:1 ≤ n ≤ 10
对于 50% 的数据满足:1 ≤ n ≤ 1000
对于 100% 的数据满足,1 ≤ n ≤ 100000
保证解存在
做法有很多:一,二分加树状数组;
二,链表(TLE一半N^2效率)
三,平衡树。
最后一个点能得到它在整个数组中的排名,得知自己的号,扣掉了一个数,因此第n-1个点也知道了,
那么如何优化找排名的过程——平衡树。
先推进去1~n,在一个一个删。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
int read()
{
int sum=0,f=1;char x=getchar();
while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
while(x>='0'&&x<='9'){sum=sum*10+x-'0';x=getchar();}
return sum*f;
}
int n,a[1000005],b[1000005],root,hh;
struct tree
{
int l,r,size,tot,h,rd;
} t[100005];
void l_swap(int &root)
{
int k=t[root].r;
t[root].r=t[k].l;
t[k].l=root;
t[k].size=t[root].size;
t[root].size=t[t[root].l].size+t[t[root].r].size+t[root].tot;
root=k;
}
void r_swap(int &root)
{
int k=t[root].l;
t[root].l=t[k].r;
t[k].r=root;
t[k].size=t[root].size;
t[root].size=t[t[root].l].size+t[t[root].r].size+t[root].tot;
root=k;
}
void build(int &root,int k)
{
if(!root)
{
root=++hh;
t[root].h=k;
t[root].size=t[root].tot=1;
t[root].rd=rand();
return;
}
t[root].size++;
if(t[root].h==k)t[root].tot++;
else
{
if(t[root].h>k)
{
build(t[root].l,k);
if(t[t[root].l].rd<t[root].rd);
r_swap(root);
}
else
{
build(t[root].r,k);
if(t[t[root].r].rd<t[root].rd)
l_swap(root);
}
}
}
void del(int &root,int k)
{
if(!root)return;
if(t[root].h==k)
{
if(t[root].tot>1)
{
t[root].tot--;
t[root].size--;
return;
}
if(t[root].l*t[root].r==0)
root=t[root].l+t[root].r;
else
{
if(t[t[root].l].rd<t[t[root].r].rd)
r_swap(root);
else
l_swap(root);
del(root,k);
}
}
else
{
t[root].size--;
if(k>t[root].h)del(t[root].r,k);
else del(t[root].l,k);
}
}
int Q(int &root,int k)
{
if(!root)return 0;
if(t[t[root].l].size+1<=k&&t[t[root].l].size+t[root].tot>=k)
return t[root].h;
if(t[t[root].l].size>=k)
return Q(t[root].l,k);
if(t[t[root].l].size<k)
return Q(t[root].r,k-t[root].tot-t[t[root].l].size);
}
int main()
{
//freopen("number.in","r",stdin);
// freopen("number.out","w",stdout);
n=read();
build(root,1);
for(int i=2;i<=n;i++)
{
a[i]=read();
build(root,i);
}
for(int i=n;i>=1;i--)
{
int k=Q(root,a[i]+1);
b[i]=k;
del(root,k);
}
for(int i=1;i<=n;i++)printf("%d\n",b[i]);
}