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;
    }
  • 相关阅读:
    分层图最短路(DP思想) BZOJ2662 [BeiJing wc2012]冻结
    动态规划 BZOJ1925 地精部落
    线性DP SPOJ Mobile Service
    线性DP codevs2185 最长公共上升子序列
    数位DP POJ3208 Apocalypse Someday
    线性DP POJ3666 Making the Grade
    杨氏矩阵 线性DP? POJ2279 Mr.Young's Picture Permutations
    tarjan强连通分量 洛谷P1262 间谍网络
    树链剖分 BZOJ3589 动态树
    二分图 BZOJ4554 [Tjoi2016&Heoi2016]游戏
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/5036414.html
Copyright © 2011-2022 走看看