火柴排队:离散化&逆序对

P1966 火柴排队

https://www.luogu.com.cn/problem/P1966

其实题目意思就是给你两列数,通过交换相邻两个数的位置,上下两个对应的数会有一个差的平方,假设就叫k吧,每两个对应的数就会有个k,最后要求所有k的总和要最小,问最少需要交换多少次?

分析:

想要最后的和小,那么每一个k都要尽量小(废话)。遵循大对大,小对小的原则(好像叫方差…)。其实我们在乎的不是这个数本身的数值,而是它在数列中的排名。就比如A数列的最大的,对应B数列中最大的,A数列中最小的,对应B数列中最小的…以此类推。所以这就要用到离散化的思想。

思路:

让我们来简单分析一下样例2:
A: 1 3 4 2
然后我们将它按大小编个码:
编码:1# 3# 4# 2#

A :   1   3   4   2
code: 1#  3#  4#  2#
//这里code表示的是排名,
//例如1是最小的排第一位,所以是1#;
//2是第二小的排第二位,所以是2# 

然后我们对第二组数动手术

A :   1   3   4   2
code: 1#  3#  4#  2#
//这里code表示的是排名,例如1是最小的排第一位,所以是1#;2是第二小的排第二位,所以是2#
B:    1  7  2  4
下标: 1# 2# 3# 4#
hope: 1# 4# 2# 3# 
//下标就是下标(后面求逆序对有用) 
//hope是我们希望排成的样子,就是跟上面的1 3 4 2对应起来:(大对大,小对小) 
//首先对A数组的1#,我们要拿最小的数去对,B数组中最小的数是B[1]=1,它的下标是1,所以填1#
//再举个例子,比如我们要对A的4#(排行老4,最大的),我们要拿B数组最大的去对,找到B[2]=7
//是最大的,那么记录下它的下标就是2#
//最后我们所hope的下标顺序就是1 4 2 3。 

然后我们就要考虑调换的问题。本来B数组的排列方式是1 2 3 4(下标),现在我们所hope的是1 4 2 3,这该怎么算呢?
其实我们不妨反过来想,与其想怎么从1 2 3 4变成 1 4 2 3,不如想怎么从1 4 2 3变成1 2 3 4这就变成了一个逆序对的事,只要求1 4 2 3中的逆序对个数就是调换次数。

逆序对:

所谓逆序对就是“反过来”。例如1 3不是,但3 1就是逆序对,(字面意思)
逆序对的一般解法就是打勾数组+前缀和,反过来统计就行了(但这题可以优化)我先来解释一下常规做法:

1 4 2 3的逆序对

0  1   2   3   4 

   
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值