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

    【题目描述】
    涵涵有两盒火柴,每盒装有n根火柴,每根火柴都有一个高度。现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:
    ,其中ai表示第一列火柴中第 i 个火柴的高度,bi表示第二列火柴中第i个火柴的高度。
    每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对99999997取模的结果。

    【输入描述】
    共三行,第一行包含一个整数n,表示每盒中火柴的数目。
    第二行有n个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。
    第三行有n个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。

    【输出描述】
    输出共一行,包含一个整数,表示最少交换次数对99999997取模的结果。

    【样例输入】

    样例1:
    4
    2 3 1 4
    3 2 1 4

    样例2:
    4
    1 3 4 2
    1 7 2 4

    【样例输出】

    样例1:
    1

    样例2:
    2

    【数据范围及提示】

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

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

    对于10%的数据,1 ≤ n ≤ 10; 

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

    对于60%的数据,1 ≤ n ≤ 1000; 

    对于100%的数据,1 ≤ n ≤ 100000,0 ≤ 火柴高度 ≤ 2^31-1。

    源代码:
    
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    struct Node
    {
        int Sum,Num;
    };
    Node i1[100001],i2[100001];
    int n,ans(0),i[100001],h[100001];
    bool Rule(Node t1,Node t2)
    {
        return t1.Sum>t2.Sum;
    }
    void Merge(int t1,int t2) //归并排序求逆序对。
    {
        if (t1==t2)
          return;
        int t=(t1+t2)>>1,x=t1,y=t+1,num=t1;
        Merge(x,t);
        Merge(y,t2);
        while (x<=t&&y<=t2)
          if (i[x]>i[y])
          {
              ans=(ans+t-x+1)%99999997; //凡事都要多动脑子,回溯上来啦,两段早就排好啦。
              h[num++]=i[y++];
          }
          else
            h[num++]=i[x++];
        while (x<=t)
          h[num++]=i[x++];
        while (y<=t2)
          h[num++]=i[y++];
        for (int a=t1;a<=t2;a++)
          i[a]=h[a];
    }
    int main() //恶心的预处理。
    {
        scanf("%d",&n);
        for (int a=1;a<=n;a++)
        {
              scanf("%d",&i1[a].Sum);
              i1[a].Num=a;
        }
        for (int a=1;a<=n;a++)
        {
              scanf("%d",&i2[a].Sum);
              i2[a].Num=a;
        }
        sort(i1+1,i1+n+1,Rule);
        sort(i2+1,i2+n+1,Rule);
        for (int a=1;a<=n;a++) //杀死脑细胞。
          i[i2[a].Num]=i1[a].Num;
        Merge(1,n);
        printf("%d",ans);
        return 0;
    }
    
    /*
        举个例子:
            5
            3 2 1 4 5
            5 2 1 4 3
        那么在第二个序列中就有:
            5应当排第5个;
            2应当排第2个;
            1应当排第3个;
            4应当排第4个;
            3应当排第1个;
        排完序不就是解吗?问题转化为求52341的逆序对,共7步。
    */
  • 相关阅读:
    删除ASP.net临时文件的操作步骤
    设置字段必录,但是直接点提交没有检查必录
    JavaWeb-Session
    Java集合类详解 转
    使用COS组件实现文件上传 转
    Java泛型详解 转
    java接口与工厂
    Vector和ArrayList的比较
    ArrayList
    关闭myeclipse自动校验特别是对js文件的校验
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5401498.html
Copyright © 2011-2022 走看看