ZYB's Premutation
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1285 Accepted Submission(s): 677
Problem Description
ZYB has a premutation P,but he only remeber the reverse log of each prefix of the premutation,now he ask you to
restore the premutation.
Pair (i,j)(i<j) is considered as a reverse log if Ai>Aj is matched.
Input
In the first line there is the number of testcases T.
For each teatcase:
In the first line there is one number N.
In the next line there are N numbers Ai,describe the number of the reverse logs of each prefix,
The input is correct.
1≤T≤5,1≤N≤50000
Output
For each testcase,print the ans.
Sample Input
1 3 0 1 2
Sample Output
3 1 2
题目大意:
第一行,测试组数
第二行,n(该数组的范围是1~n,所以不存在离散化问题)
第三行,n个数,每个数字表示在该位置之前的逆序对的数量
比如a[5]=5,表示在前五个位置有5个逆序对,但并不是在第五个位置上存在5个逆序对!!!
以下是官方题解
权值线段树找一下第k个什么的很方便
#include<cstdio>
#include<iostream>
#include<cstring>
#define MAXN 50005
using namespace std;
struct forma
{
int l,r,val,num;
} tree[MAXN*4];
int a[MAXN],ans[MAXN];
void build(int root,int l,int r)
{
tree[root].l=l;
tree[root].r=r;
tree[root].num=r-l+1;
if(l==r)
{
tree[root].val=l;
return ;
}
int mid=(l+r)>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
}
int query(int root,int k)
{
if(tree[root].l==tree[root].r)
return tree[root].val;
if(tree[root<<1].num>=k)
return query(root<<1,k);
else
return query(root<<1|1,k-tree[root<<1].num);
}
void update(int root,int pos)
{
tree[root].num--;
if(tree[root].l==tree[root].r)
return ;
if(pos<=tree[root<<1].r)
update(root<<1,pos);
else
update(root<<1|1,pos);
return ;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d",&n);
memset(a,0,sizeof(a));
memset(ans,0,sizeof(ans));
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
build(1,1,n);
for(int i=n; i>=1; i--)
{
ans[i]=query(1,i-(a[i]-a[i-1])); //从剩下的数中选择a[i]-a[i-1]+1大的
update(1,ans[i]);
}
for(int i=1; i<n; i++)
printf("%d ",ans[i]);
printf("%d\n",ans[n]);
}
return 0;
}