要想对任意(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. Spring RPC 入门学习(1)-HelloWorld入门

    Spring搭建RPC环境 第一,下载所需要的jar包,下载地址:https://yunpan.cn/cPErQeANrSMyB (提取码:63e5),见下图: 第二,新建动态WebProject,把 ...

  2. 《Linux内核设计与实现》第三章读书笔记

    一.进程(任务)描述 1.进程是处于执行期的程序:除了可执行程序代码,还包括打开的文件.挂起的信号.内核内部数据.一个或者多个执行线程等多种资源 线程是在进程活动中的对象:内核调度的对象是线程而不是进 ...

  3. 2017-2018-2 1723《程序设计与数据结构》第十一周作业 & 实验三 & (总体)第三周结对编程 总结

    作业地址 第十一次作业:https://edu.cnblogs.com/campus/besti/CS-IMIS-1723/homework/1933 (作业界面已评分,可随时查看,如果对自己的评分有 ...

  4. Proxy 示例

    package cn.proxy03; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; imp ...

  5. 第三个Sprint ------第九天

    四则运算APP内侧: 1将APP安装包apk发到QQ群(班群),让自己班的同学率先体检.通过同学们的反馈.及时处理好bug,快速迭代. 2将APP下载链接发到微信朋友圈,QQ空间,让其他学校的同学也体 ...

  6. 第三个Sprint ------第三天

    出题界面代码 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns ...

  7. Android动画总结

    本文总结常用属性方法等,详细学习可使用如下郭霖大神文章: Android属性动画完全解析(上),初识属性动画的基本用法 Android属性动画完全解析(中),ValueAnimator和ObjectA ...

  8. ES next & Async Await

    ES next & Async Await https://jestjs.io/docs/en/asynchronous#async-await ES7 new async () => ...

  9. HTML5 & how to download SVG in js

    HTML5 & how to download SVG in js how to download SVG in js http://dinbror.dk/blog/how-to-downlo ...

  10. <a>與<link>的區別

    <a>連接網頁: <link>定義文檔與外部資源的關係或引用外部樣式表,屬性ref表示連接對象的類型,stylesheet表示連接的是css類型的. 參考資料: https:/ ...