HDU 6318 Swaps and Inversions【归并排序】

题目链接

题目意思

现在有一个n个数值的无序序列,现在要求这个序列中的逆序对个数,并且每个逆序对需要支付x元。但是那你可以耍一个小把戏就是支付y元将这个序列中相邻的两个数值交换。现在问你你需要的最小支付是多少元。

解题思路

题目意思就是问你一个序列中有多少个逆序对。我们如果支付y元将两个相邻的数值进行交换,那么就消除了一个逆序对,和直接算逆序对的个数是相同的意思。那么问题就在于怎样才能有最小的花费。如果逆序对支付的少,那么我们就直接求逆序对个数乘上每个逆序对需要支付的钱。同理如果交换数值花费的少,那么我们就将序列中所有的逆序对都用交换来消除,这样得到的花费就是交换的花费乘上逆序对个数。
要求逆序对的个数我们就用到了归并排序算法,用归并算法去求一个序列中的逆序对个数。

代码部分
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=1e5+10;
int n,x,y;
int a[maxn],b[maxn];
inline ll merge(int l, int mid, int r)///合并函数
{
    int i, j, k;
    i = l;
    j = mid + 1;                        ///避免重复比较a[mid]
    k = 0;
    ll ans=0;
    while (i <= mid && j <= r)        ///把两个数组从第一个开始比较小的加入整理数组直到一个数组都加入
    {
        if (a[i] > a[j])
        {
            ans+=(mid-i+1);
            b[k++] = a[j++];
        }
        else
            b[k++] = a[i++];
    }
    while (i <= mid)        ///将剩下的的全部加入整理后的数组
        b[k++] = a[i++];
    while (j <= r)
        b[k++] = a[j++];
    for (i = 0; i < k; i++)         ///把整理后的数组替代掉之前的未整理的
        a[l + i] = b[i];    ///注意,应从a[l+i]开始赋值
    return ans;
}
inline ll merge_sort( int l, int r)
{
    ll ans=0;
    if (l < r)    ///细分到每一个元素都为一个数组后开始合并
    {
        int mid = (l + r)>>1;
        ans += merge_sort(l,mid);                    ///对左边进行排序
        ans += merge_sort(mid+1,r);                  ///对右边进行排序
        ans += merge(l, mid, r);                    ///把排序好的数据合并
    }
    return ans;
}
int main()
{
    while(scanf("%d%d%d",&n,&x,&y)!=EOF)
    {
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
        }
        ll ans = merge_sort(1,n);
        ll temp=0;
        if(x>y)
        {
            temp=ans * y;
        }
        else
        {
            temp=ans * x;
        }
        cout<<temp<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值