zoukankan      html  css  js  c++  java
  • Luogu_1966_火柴排队

    题目描述

    涵涵有两盒火柴,每盒装有(n)根火柴,每根火柴都有一个高度。 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为:$ sum (a_i-b_i)^2$

    其中(a_i) 表示第一列火柴中第(i)个火柴的高度,(b_i)表示第二列火柴中第(i)个火柴的高度。

    每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 (99,999,997)取模的结果。

    输入输出格式

    输入格式:

    共三行,第一行包含一个整数(n),表示每盒中火柴的数目。

    第二行有(n)个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。

    第三行有(n)个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。

    输出格式

    一个整数,表示最少交换次数对(99,999,997)取模的结果。

    样例

    INPUT

    4
    2 3 1 4
    3 2 1 4

    OUTPUT

    1

    INPUT

    4
    1 3 4 2
    1 7 2 4

    OUTPUT

    2

    HINT

    【输入输出样例说明1】

    最小距离是(0),最少需要交换(2)次,比如:交换第(1)列的前(2)根火柴或者交换第(2)列的前(2)根火柴。

    【输入输出样例说明2】

    最小距离是(10),最少需要交换(2)次,比如:交换第(1)列的中间(2)根火柴的位置,再交换第(2)列中后(2)根火柴的位置。

    【数据范围】

    对于(10%)的数据, (1≤n≤10)

    对于 (30%)的数据,(1≤n≤100)

    对于 (60%)的数据,(1≤n≤1,000)

    对于 (100%)的数据,(1 ≤ n ≤ 100,000,0≤)火柴高度(≤maxlongint)

    SOLUTION

    离散+树状数组求逆序对

    题目这个换来换去然后得到最小距离的要求很容易就让人想到有一道名为“多米诺骨牌”的dp题。但实际上并不一样,那道题是上下换,两个序列的组成很可能会改变很大,而且两题的数据范围等也存在差异,反正这题就不能用那种dp方法做。

    本题的核心思路就是:若要使(sum (a_i-b_i)^2)最小,每对(abs(a_i-b_i))的对答案的贡献应该尽可能的少,然后就可以想到若是把(a,b)两个序列从小到大排序,然后得到的两个序列就能构成最优答案。那么怎么计算交换次数呢?我们根据未排序序列的(a[i])与其所对应的(b[i])位置来计算交换次数。

    引用@ZJYelizaveta的题解部分内容:
    "好了,这道题目的精华在于对于新建序列!

    假设我们现在有离散化后的序列(a = {4, 3, 1, 2})(b = {1, 3, 2, 4})

    我们令(q[a[i]] = b[i]),相当于以 (a[i])为关键字对序列 b[i]b[i]b[i] 排序。

    若序列 (a) 与序列(b)相等,那么此时(q[a[i]])应该等于(a[i])的,也就是(q[i] = i)

    那么也就是说如果我们想让序列(a)与序列(b)相等,那么我们需要让(q)升序排列。

    问题就变为,将原本乱的(q)序列升序排列的最少交换次数。

    诶,这不就是逆序对吗?

    于是,用树状数组求之即可。
    "

    并且这里要注意:我们存在(q)里的(c,d)都代表的是(a,b)离散后的位置,因为我们的最优解只需要位置相对应就够了,不一定要求达到真正的(a,b)从小到大升序排列。这一点要十分注意!!!

  • 相关阅读:
    python中文编码
    Python习题纠错1
    Python中的变量
    Python之注释
    python初步学习
    java输入数据并排序
    五月最后一天
    @component注解
    多线程回顾
    赖床分子想改变--
  • 原文地址:https://www.cnblogs.com/hkpls/p/9798184.html
Copyright © 2011-2022 走看看