全排列 UVA 11525 Permutation

 

题目传送门

题意:训练指南P248

分析:逆向考虑,比如一个全排列:7345261,它也可以表示成题目中的形式,第一个数字7是由6 * (7 - 1)得到的,第二个数字3有2 * (7 - 2)得到,所以只要树状数组单点修改二分(找最远的因为有些位置是0)查询当前第s[i] + 1的数字(在BIT中指前p项和为s[i] + 1)。

#include <bits/stdc++.h>
using 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;
}

  

posted @ 2016-02-26 19:43  Running_Time  阅读(321)  评论(0编辑  收藏  举报