ZYB's Premutation
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 977 Accepted Submission(s): 496
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.
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
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
Source
题意:给出一个序列P位置i的逆序前缀,要求还原这个序列,定义i<j且Ai>Aj时Ai为Aj的逆序
题解:先把逆序前缀分解成位置i的逆序,只要用a[i]-a[i-1]即可.然后反向遍历,对于位置i,逆序为a[i],那么设在位置i+1~n中,比i大的数出现了x个,
那么位置i的数的大小就是n-a[i]-x
/*
题意:给出一个序列P位置i的逆序前缀,要求还原这个序列,定义i<j且Ai>Aj时Ai为Aj的逆序
题解:先把逆序前缀分解成位置i的逆序,只要用a[i]-a[i-1]即可.然后反向遍历,对于位置i,逆序为a[i],那么设在位置i+1~n中,比i大的数出现了x个,
那么位置i的数的大小就是n-a[i]-x,过程用线段树维护一下就可以了
*/
#include<cstdio>
#include<algorithm>
#include<string.h>
#include<stdlib.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn = 5e4 + 5;
int sum[maxn<<2],a[maxn],ans[maxn];
void PushUP(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt){
if(l==r) {sum[rt]=1;return;}
int m=(l+r)>>1;
build(lson);
build(rson);
PushUP(rt);
}
int query(int x,int l,int r,int rt){
if(l==r) {sum[rt]=0;return l;}
int m=(l+r)>>1;
int ret=0;
if(sum[rt<<1|1]<=x) ret=query(x-sum[rt<<1|1],lson);
else ret=query(x,rson);
PushUP(rt);
return ret;
}
int main(){
int T,n;
//freopen("in.txt","r",stdin);
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,n,1);
for(int i=n;i>0;i--) {
a[i]-=a[i-1]; //得到位置i的逆序数
int x=query(a[i],1,n,1);
ans[i]=x;
}
for(int i=1;i<=n;i++) printf("%d%c",ans[i],i==n?'\n':' ');
}
return 0;
}