题意:训练指南P248
分析:逆向考虑,比如一个全排列:7345261,它也可以表示成题目中的形式,第一个数字7是由6 * (7 - 1)得到的,第二个数字3有2 * (7 - 2)得到,所以只要树状数组单点修改二分(找最远的因为有些位置是0)查询当前第s[i] + 1的数字(在BIT中指前p项和为s[i] + 1)。
#includeusing namespace std;const int N = 1e5 + 5;int s[N];struct BIT { int c[N], sz; void init(int num) { memset (c, 0, sizeof (c)); sz = num; } void updata(int i, int x) { while (i <= sz) { c[i] += x; i += i & -i; } } int query(int i) { int ret = 0; while (i > 0) { ret += c[i]; i -= i & -i; } return ret; } int bsearch(int l, int r, int kth) { while (l < r) { int mid = l + r >> 1; if (query (mid) < kth) l = mid + 1; else r = mid; } return r; }}bit;int main(void) { int T; scanf ("%d", &T); while (T--) { int k; scanf ("%d", &k); bit.init (k); for (int i=1; i<=k; ++i) { scanf ("%d", &s[i]); bit.updata (i, 1); } for (int i=1; i<=k; ++i) { int p = bit.bsearch (1, k, s[i] + 1); if (i > 1) printf (" "); printf ("%d", p); bit.updata (p, -1); } puts (""); } return 0;}