zoukankan      html  css  js  c++  java
  • HDU 5592 ZYB's Premutation(树状数组+二分)

    题意:给一个排列的每个前缀区间的逆序对数,让还原 原序列。

    思路:考虑逆序对的意思,对于k = f[i] - f[i -1],就表示在第i个位置前面有k个比当前位置大的数,那么也就是:除了i后面的数字之外,它是在剩下的数字当中第k+1大的。

    知道这个之后,可以用树状数组来帮助找出剩下的数中第k大的数,刚开始我们可以让1~n中每个元素都标记为1,那么他们的前缀和就代表它是第几小。所以,我们可以对于他们的和来二分快速寻找第k大数。其实在树状数组里面是按照第(i-k)小来找的。找完之后要删除这个元素的值。将它标记为0;

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 50005;
    int f[maxn];
    int c[maxn];
    int ans[maxn];
    int lowbit(int x)
    {
        return x & (-x);
    }
    void add(int pos, int num, int n)
    {
        while (pos <= n)
        {
            c[pos] += num;
            pos += lowbit(pos);
        }
    }
    int getSum(int pos)
    {
        int sum = 0;
        while (pos > 0)
        {
            sum += c[pos];
            pos -= lowbit(pos);
        }
        return sum;
    }
    void init(int n)
    {
        memset(c, 0, sizeof(c));
        for (int i = 1; i <= n; i++)
            add(i, 1, n);
    }
    int search(int k, int n) 
    {
        int l = 1, r = n, mid;
        while (l <= r)
        {
            mid = (l + r) / 2;
            int sum = getSum(mid);
            if (sum >= k) r = mid - 1;
            else l = mid + 1;
        }
        return l;
    }
    int main()
    {
        int T, n;
        scanf("%d", &T);
        while (T--)
        {
            scanf("%d", &n);
            init(n);
            for (int i = 1; i <= n; i++)
                scanf("%d", &f[i]);
            for (int i = n; i >= 1; i--)
            {
                int k = f[i] - f[i - 1];//第k+1大
                k = i - k;//在剩下的里面第i - k 小
                int pos = search(k, n);//二分找出第k小的位置
                ans[i] = pos;
                add(pos, -1, n);
            }
            for (int i = 1; i < n; i++) printf("%d ", ans[i]);
            printf("%d
    ", ans[n]);
        }
        return 0;
    }
  • 相关阅读:
    leetcode第14题最长公共前缀
    什么是神经网络
    获取url "?" 后面的字符串
    第一天
    C#和.Ne学习第九天
    C#和.Ne学习第八天
    格式化输出
    C#和.Ne学习
    C#和.Ne学习第七天
    C#类型转换
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/5036414.html
Copyright © 2011-2022 走看看