要想对任意(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. Python - 列表解析式

    列表解析——用来动态地创建列表 [expr for iter_var in iterable if cond_expr] 例子一: map(lambda x: x**2, range(6)) [0, ...

  2. python报错问题解决:'ascii' codec can't encode character

    之前部署了openstack虚拟化环境,有一天在使用nova list查看虚拟机的时候,突然报错!如下: [root@linux-node1 src]# nova listERROR (Unicode ...

  3. snmpd.conf 配置

    开启snmp后,一些指标获取不到,需要配置snmpd.conf文件,如下图所示 参考文章:http://blog.csdn.net/flyingfalcon/article/details/47831 ...

  4. php 中 opendir() readdir() scandir()

    opendir(path,context)若成功,则该函数返回一个目录流,否则返回 false 以及一个 error.可以通过在函数名前加上 “@” 来隐藏 error 的输出. readdir() ...

  5. Dubbo原理和源码解析之服务暴露

    github新增仓库 "dubbo-read"(点此查看),集合所有<Dubbo原理和源码解析>系列文章,后续将继续补充该系列,同时将针对Dubbo所做的功能扩展也进行 ...

  6. vs感受,由于我的电脑装了俩年了!我直接写感受吧

    个人感受:最初的感觉,最开始装vs是因为我的电脑8.1不兼容vc6.0(一个挺坑的编程软件),最开始用vs的时候我还是一个小白什么都不懂,vs创建项目实在是太复杂,不看教程根本看不懂,也许是它能包容的 ...

  7. “北航学堂”M2阶段postmortem

    “北航学堂”M2阶段postmortem 设想和目标 1. 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 这个问题我们在M1阶段的时候就已经探讨的比较明确了,就是 ...

  8. M2 终审

    1.团队成员简介 左边:马腾跃 右边:陈谋 左上:李剑锋  左下:仉伯龙 右:卢惠明 团队成员及博客: 李剑锋:        Blog:      http://www.cnblogs.com/Po ...

  9. win10装MySQL5.7

    越来越发现装MySQL很费劲啊,装了N次,都很懵逼,找对的解决方案很重要. Mysql5.7下载地址:http://xiazai.zol.com.cn/detail/4/33431.shtml 安装步 ...

  10. java注解的简单介绍

    什么是注解 1.注解就是Annontation,Annontation是Java5开始引入的新特征,中文名称叫做注解,它提供了一种安全的类似注释的机制,可以起到减少配置的成果,给程序起到辅助性的作用 ...