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
思路:
稍微转换一下a[i] - a[i - 1],就变成了经典的线段树的题目了
/*======================================================
# Author: whai
# Last modified: 2015-12-07 12:38
# Filename: c.cpp
======================================================*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <stack>
using namespace std;
#define LL __int64
#define PB push_back
#define P pair<int, int>
#define X first
#define Y second
#define LS (2 * n)
#define RS (2 * n + 1)
const int N = 5 * 1e4 + 5;
int a[N];
int ans[N];
struct Seg {
int l, r, size;
}seg[4 * N];
void up(int n) {
seg[n].size = seg[LS].size + seg[RS].size;
}
void build(int l, int r, int n) {
seg[n].l = l; seg[n].r = r;
if(l == r) {
seg[n].size = 1;
return ;
}
int mid = (l + r) >> 1;
build(l, mid, LS);
build(mid + 1, r, RS);
up(n);
}
int get_id(int rank, int n) {
if(seg[n].l == seg[n].r) return seg[n].l;
if(rank <= seg[LS].size) {
return get_id(rank, LS);
} else {
rank -= seg[LS].size;
return get_id(rank, RS);
}
}
void update(int p, int n) {
if(seg[n].l == seg[n].r) {
--seg[n].size;
return ;
}
int mid = (seg[n].l + seg[n].r) >> 1;
if(p <= mid) update(p, LS);
else update(p, RS);
up(n);
}
void gao(int n) {
for(int i = n - 1; i > 0; --i) {
a[i] -= a[i - 1];
}
for(int i = 0; i < n; ++i) {
a[i] = i + 1 - a[i];
}
//for(int i = 0; i < n; ++i) {
// cout<<a[i]<<' ';
//}
//cout<<endl;
build(1, n, 1);
for(int i = n - 1; i >= 0; --i) {
ans[i] = get_id(a[i], 1);
update(ans[i], 1);
}
for(int i = 0; i < n; ++i) {
printf("%d%c", ans[i], i == n - 1 ? '\n' : ' ');
}
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
int n;
scanf("%d", &n);
for(int i = 0; i < n; ++i) {
scanf("%d", &a[i]);
}
gao(n);
}
return 0;
}