ZYB's Premutation
Accepts: 218
Submissions: 983
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
问题描述
ZYB有一个排列P,但他只记得P中每个前缀区间的逆序对数,现在他要求你还原这个排列. (i,j)(i<j)被称为一对逆序对当且仅当Ai>Aj
输入描述
第一行一个整数T表示数据组数。 接下来每组数据: 第一行一个正整数N,描述排列的长度. 第二行N个正整数Ai,描述前缀区间[1,i]的逆序对数. 数据保证合法. 1≤T≤5,1≤N≤50000
输出描述
T行每行N个整数表示答案的排列.
输入样例
1 3 0 1 2
输出样例
3 1 2
思路:
这题与这题(点我)的对立,对立那题是左边有几个比自己小,而这题变成了,右边有几个比自己小。所以这题可以转化为对立的那题。所以只要在右边找到有几个比自己小的数,然后从大到小存,就行了。
AC代码:
#include<iostream> #include<algorithm> #include<cstring> #include<string> #include<cstdio> using namespace std; #define lson (rt<<1) #define rson (rt<<1|1) #define T 50010 struct node { int L,R,mid; int sum; }tree[T<<2]; int v[T],ans[T],c; void Pushup(int rt) { tree[rt].sum = tree[lson].sum+tree[rson].sum; } void build(int rt,int L,int R) { tree[rt].L = L,tree[rt].R = R; tree[rt].mid = (L+R)>>1; if(L==R){ tree[rt].sum =1; return; } build(lson,L,tree[rt].mid); build(rson,tree[rt].mid+1,R); Pushup(rt); } void Update(int rt,int pos) { if(tree[rt].L==tree[rt].R){ ans[c--] =tree[rt].L; tree[rt].sum=0; return; } if(pos>tree[rson].sum){ Update(lson,pos-tree[rson].sum); } else { Update(rson,pos); } Pushup(rt); } int main() { #ifdef zsc freopen("input.txt","r",stdin); #endif int n,m,i; scanf("%d",&n); while(n--) { scanf("%d",&m); c=m; for(i=1;i<=m;++i){ scanf("%d",&v[i]); } for(i=m;i>0;--i)v[i]=v[i]-v[i-1]+1; build(1,1,m); for(i=m;i>0;--i){ Update(1,v[i]); } for(i=1;i<=m-1;++i){ printf("%d ",ans[i]); } printf("%d\n",ans[m]); } return 0; }
只是因为数组从0开始还是从1开始,就Wa了,真心无语。(发现错误了,原来是v【0】未加一。。。。)
WA代码:
#include<iostream> #include<algorithm> #include<cstring> #include<string> #include<cstdio> using namespace std; #define lson (rt<<1) #define rson (rt<<1|1) #define T 50010 struct node { int L,R,mid; int sum; }tree[T<<2]; int v[T],ans[T],c; void Pushup(int rt) { tree[rt].sum = tree[lson].sum+tree[rson].sum; } void build(int rt,int L,int R) { tree[rt].L = L,tree[rt].R = R; tree[rt].mid = (L+R)>>1; if(L==R){ tree[rt].sum =1; return; } build(lson,L,tree[rt].mid); build(rson,tree[rt].mid+1,R); Pushup(rt); } void Update(int rt,int pos) { if(tree[rt].L==tree[rt].R){ ans[c--] =tree[rt].L; tree[rt].sum=0; return; } if(pos>tree[rson].sum){ Update(lson,pos-tree[rson].sum); } else { Update(rson,pos); } Pushup(rt); } int main() { #ifdef zsc freopen("input.txt","r",stdin); #endif int n,m,i; scanf("%d",&n); while(n--) { scanf("%d",&m); c=m; for(i=0;i<m;++i){ scanf("%d",&v[i]); } for(i=m-1;i>0;--i)v[i]=v[i]-v[i-1]+1; build(1,1,m); for(i=m-1;i>=0;--i){ Update(1,v[i]); } for(i=1;i<=m-1;++i){ printf("%d ",ans[i]); } printf("%d\n",ans[m]); } return 0; }