要想对任意(ai,bi)和(a和b­j),当ai<aj时,都有bi<=bj;当ai>=aj时,bi>=bj,当对a进行升序排序后(b同时发生改变,从而不改变值,最后有a1<=a2<=…<=an),必须满足b1<=b2<=…<=b­n

否则,必存在(ai,bi)和(a和b­j),有ai<aj且bi>bj,交换ai和aj后,(aj*bi+ ai*bj)-( ai*bi+ aj*bj)=(aj-ai)*( bi-bj)>0,数值更小,即不是所满足的序列。

唯有满足条件“对任意(ai,bi)和(a和b­j),当ai<aj时,都有bi<=bj;当ai>=aj时,bi>=bj”的序列才是值最小的序列。

最后目的是:对任意(ai,bi)和(a和b­j),当ai<aj时,都有bi<=bj;当ai>=aj时,bi>=bj,其中题目限制“同一列火柴的高度互不相同”,所以对a,b序列进行从小到大排序,数的编号具有唯一性,即最后a,b两个序列中,ai在a序列的编号等于bi在b序列的编号。

每一次操作,一列(a,b数组)中相邻的两个数进行交换,其中ai和ai+1的交换等效于bi和bi+1的交换。我们可以固定a序列不动,修改b序列,最优的操作满足操作次数最少。

b序列第i位的数要移到目标位置第vi位中,求出v序列。b序列的数的移动顺序是按照对应的v序列的数从小到大。当目标位置为第vi位对应的bi(原来)需要移动时,前面的第1~vi-1位已经排好,而其它bi(原来)前面的数为还未移动的数,即对应的v序列的值大于vi。所以bi(原来)需要向左移动的次数为满足j<i and vj>vi所有的j的个数。

即总的操作次数为v序列的逆序对的个数。有两种方法求逆序对使得时间复杂度为O(nlogn):

1.归并排序+统计

2.离散化+树状数组

Code:

 #include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define yu 99999997
#define maxn 100000
 
struct node
{
    long value,pos;
}a[maxn+],b[maxn+];
long v[maxn+],t[maxn+],ans;
 
int cmp(const void *a,const void *b)
{
    if ((*(struct node *)a).value<(*(struct node *)b).value)
        return -;
    else
        return ;
}
 
void mergesort(long l,long r)
{
    if (l==r)
        return ;
    long mid,x,y,z,i;
    mid=(l+r)/;
    mergesort(l,mid);
    mergesort(mid+,r);
    for (i=l;i<=r;i++)
        t[i]=v[i];
    x=l;
    y=mid+;
    z=l;
    while (x<=mid && y<=r)
    {
        //两个数相等时让左边的数先加,因为相同的数不能凑成一对
        if (t[x]<=t[y])
        {
            v[z]=t[x];
            x++;
            //v[x] > v[mid+1]~v[y-1]
            ans=(ans+(y-mid-))%yu;
        }
        else if (t[x]>t[y])
        {
            v[z]=t[y];
            y++;
        }
        z++;
    }
    if (x<=mid)
    {
        //v[x] > v[mid+1]~v[r]
        ans=(ans+(mid-x+)*(r-mid))%yu;
        while (z<=r)
        {
            v[z]=t[x];
            x++;
            z++;
        }
    }
    else
    {
        while (z<=r)
        {
            v[z]=t[y];
            y++;
            z++;
        }
    }
}
 
int main()
{
    long n,i;
    scanf("%ld",&n);
    for (i=;i<=n;i++)
    {
        scanf("%ld",&a[i].value);
        a[i].pos=i;
    }
    for (i=;i<=n;i++)
    {
        scanf("%ld",&b[i].value);
        b[i].pos=i;
    }
    qsort(a+,n,sizeof(struct node),cmp);
    qsort(b+,n,sizeof(struct node),cmp);
    for (i=;i<=n;i++)
        v[b[i].pos]=a[i].pos;
    ans=;
    mergesort(,n);
    printf("%ld\n",ans);
    return ;
}
/*
Input:
10
10 1 5 2 7 4 9 3 6 8
7 5 1 8 10 4 6 2 3 9
Output:
18
*/

感慨一下:想当初比赛做这道题,没有想到是逆序对,最终没有做出来,留下遗憾。现在终于写了个题解,把这道题做了,算是对遗憾的一种弥补吧。
希望自己可以走得更远……

noip2013火柴排队_Solution的更多相关文章

  1. LOJ2609. NOIP2013 火柴排队 【树状数组】

    LOJ2609. NOIP2013 火柴排队 LINK 题目大意: 给你两个数列,定义权值∑i=1(ai−bi)^2 问最少的操作次数,最小化权值 首先需要发现几个性质 最小权值满足任意i,j不存在a ...

  2. [树状数组+逆序对][NOIP2013]火柴排队

    火柴排队 题目描述 涵涵有两盒火柴,每盒装有n根火柴,每根火柴都有一个高度.现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:∑ (ai-bi)2,i=1,2,3,. ...

  3. NOIP2013火柴排队[逆序对]

    题目描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2 其中 ai 表示 ...

  4. [NOIP2013] 火柴排队(归并排序)

    题目描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2 其中 ai 表示 ...

  5. noip2013 火柴排队

    题目描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2 其中 ai 表示 ...

  6. jzoj[1438]NOIP2013火柴排队

    读题: 相邻两个火柴可以交换?两个火柴序列?嗅到了归并排序的味道. 读完题目之后,我们可以知道,如果想要交换次数最少,可以先固定一个序列不变,比如说a序列不变,变b序列 样例是 4 2 3 1 4 3 ...

  7. NOIP2013火柴排队

    Solution 恕我直言,这题是真的坑. 对于这道题,一个很显然的思路是对于A B两个序列,他们交换完后相对的两个数在原序列中的相对大小是相同的,于是我们就把序列按照A排序,在把B离散化,求逆序对, ...

  8. NOIp2013 火柴排队【逆序对/思维】 By cellur925

    题目大意:给你两列数\(ai\)和\(bi\),你可以交换每列数中相邻的两个数,求一个最小交换次数使\(\sum_{i=1}^{n}(a_i-b_i)^2\) 最小. 最后满足条件的两个序列一定是各个 ...

  9. NOIP 2013 火柴排队

    洛谷 P1966 火柴排队 洛谷传送门 JDOJ 2227: [NOIP2013]火柴排队 D1 T2 JDOJ传送门 Description 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高 ...

随机推荐

  1. Segment Occurrences(string find函数)

    Description You are given two strings s and t, both consisting only of lowercase Latin letters.The s ...

  2. 【实践报告】Linux实践二

    3.编译并安装内核与模块 sudo make bzImage –j3         编译内核 sudo make modules –j3         编译模块 sudo make modules ...

  3. sqoop 使用笔记

    好久没有更新自己技术博客,现在开始工作了,把自己遇到的问题写到这里边来 主要把自己的问题写出来,分享给大家 sqoop 导入数据时候 有时候会遇到mysql 中有sql 中的关键字 这时候如果直接导出 ...

  4. MyBatis中if,where,set标签

    <if>标签 <select id="findActiveBlogWithTitleLike" resultType="Blog"> S ...

  5. github使用心得和链接

    在本次使用github过程中,刚打开github主界面的时候,吓了一跳,满眼的英文加上各种没用过的命令,真是一个头两个大,废话不多说,下面我就说一下我在使用github过程中遇到的两个问题.: 问题一 ...

  6. 现代程序设计 homework-01

    搞了6个小时individual project...看看博客做一做第一次现代程序设计作业 1) 建立 GitHub 账户, 把课上做的 “最大子数组之和” 程序签入 我的github地址是https ...

  7. SVN上传下载项目

    1 本机安装svn服务器 1.1    创建新库 创建分支, Trunk:主干, Tags:分支节点 Branches:分支 比如说我们现在tomcat出了6.0以后已经定版了,但是还得继续开发呀,开 ...

  8. PAT L3-008 喊山

    https://pintia.cn/problem-sets/994805046380707840/problems/994805050709229568 喊山,是人双手围在嘴边成喇叭状,对着远方高山 ...

  9. Ubuntu 服务器指南

    https://help.ubuntu.com/lts/serverguide/   Jabber Instant Messaging Server https://help.ubuntu.com/l ...

  10. Windows10 RedStone 1使用Bash体验

    很多年前,记得在Windows Server2008的Feature里发现了Windows Subsystem For Unix,当时也不知道干啥用的,还以为是Samba协议用的呢. 今天,发现Win ...