美文网首页
算法设计与分析 2.1 杰哥和序列 (求逆序数算法)

算法设计与分析 2.1 杰哥和序列 (求逆序数算法)

作者: 阿明DunDunDun | 来源:发表于2019-11-09 13:46 被阅读0次

    题目描述:

    杰哥喜欢单调不下降的序列,因为他觉得这样的序列有美感。

    今天杰哥得到了一个长度为N的序列D,但是他今天心情不好,他把序列丢给了你,要你把他变成单调不下降的序列。

    你可以花费A单位的时间交换序列中两个相邻的元素,当然,你也可以选择干一半摸鱼罢工。

    最后你要把序列还给杰哥,但是如果杰哥发现序列中每有一个逆序对,就会把你抓过去,训话B单位时间。

    你想花最少的时间(主动交换元素+被动被杰哥训话的时间)把这个事解决了,问这个时间是多少。

    逆序对的定义:存在两个整数i和j,满足1<=i<j<=N,且Di>Dj,则 <Di,Dj> 这个有序对称为 D 的一个逆序对。

    输入格式:

    输入第一行为三个空格隔开的正整数 N、A、B,代表序列长度为N,A和B的含义见题面。

    接下来一行有 N 个整数,第i个数表示序列的第ii个元素DiDi。

    对于80%的数据,1<=N,A,B<=2000 。

    对于100%的数据,1<=N,A,B<=100000,序列元素非负且在int范围内。

    输出格式:

    输出你要花费的最少时间。

    样例输入:

    2 1 2
    2 1

    样例输出:

    1

    解法:

    先弄懂逆序对的含义,其实最重要的一点就是,逆序对的数量就是要交换相邻达到非递减的最小交换次数,也就是说每交换一次,逆序对就会少一对。

    因此本题其实根本不是贪心算法或者动态规划,就是求出所有的逆序对数量,然后看是交换代价小还是训话代价小,要么全部交换,要么全部训话。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    const int N = 100000;
    
    int a[N], tmp[N];
    int ans;
    
    void Merge(int l, int m, int r) {
        int i = l;
        int j = m + 1;
        int k = l;
        while (i <= m && j <= r) {
            if (a[i] > a[j]) {
                tmp[k++] = a[j++];
                ans += m - i + 1;
            }
            else {
                tmp[k++] = a[i++];
            }
        }
        while (i <= m)
            tmp[k++] = a[i++];
        while (j <= r)
            tmp[k++] = a[j++];
        for (int i = l; i <= r; i++)
            a[i] = tmp[i];
    }
    
    void Merge_sort(int l, int r) {
        if (l < r) {
            int m = (l + r) >> 1;
            Merge_sort(l, m);
            Merge_sort(m + 1, r);
            Merge(l, m, r);
        }
    }
    
    int main() {
        int n, A, B;
        cin >> n >> A >> B;
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        ans = 0;
        Merge_sort(0, n - 1);
        if (A < B) ans = ans * A;
        else ans = ans * B;
        cout << ans << endl;
        return 0;
    }
    

    最后得分是8分。分析了原因是最后两个点数据大,溢出了。

    改进思路:

    把所有的int型,改成long型,解决溢出问题,10分。

    相关文章

      网友评论

          本文标题:算法设计与分析 2.1 杰哥和序列 (求逆序数算法)

          本文链接:https://www.haomeiwen.com/subject/syfnbctx.html