首页 > 其他分享 >4877: 火柴排队 归并排序

4877: 火柴排队 归并排序

时间:2023-08-16 22:24:40浏览次数:44  
标签:4877 移动 int mid 最小 ++ 火柴 归并 排序

描述

 

 

涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:Σ(ai-bi)^2, i=1~n,其中ai表示第一列火柴中第i个火柴的高度,bi表示第二列火柴中第i个火柴的高度。

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

 

 

输入

 

 

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

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

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

 

 

输出

 

 

输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果。

 

 

样例输入

 

4
2 3 1 4
3 2 1 4

样例输出

 1

提示

 

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

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

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

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

首先我们知道要使得原式最小,只有在两列数的第K大相互对应的时候最小(证明略)。

那么问题就转化成了:

把数列b的数字大小关系移动成数列a的大小关系所需要的最小移动次数。

如何做呢?举个例子:

3 2 4 1

2 4 1 3

现在要求最小移动次数是的数列b变为:3 2 4 1

那么说明原位置1要移动到2,2移动到3,3移动到4,4移动到1(这里的数字指位置)。对应到一个新数列中即为:

2 3 4 1

目标状态为:

1 2 3 4

那么答案就为让这个新序列有序的最小移动次数,于是就是裸的逆序对了,用树状数组或归并排序均可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+10,inf = 0x3f3f3f3f,mod = 99999997;
struct node{
    int bh,num;
};
node a[N],b[N];
ll c[N],r[N];
ll n,sum;
bool cmp(node a,node b)
{
    return a.num < b.num;
}
void merge(int s,int mid,int t)
{
    int i = s,k = s,j = mid+1;
    while(i<=mid && j<=t)
    {
        if(c[i]>c[j])
        {
            r[k++] = c[j++];
            sum += mid-i+1;
        }
        else r[k++] = c[i++];
    }
    while(i<=mid) r[k++] = c[i++];
    while(j<=t) r[k++] = c[j++];
    for(int x = s;x <= t;x++)c[x] = r[x];
}
void mergesort(int s,int t)
{
    if(s<t)
    {
        int mid = (s+t)>>1;
        mergesort(s,mid);
        mergesort(mid+1,t);
        merge(s,mid,t);
    }
}
int main()
{
    cin >> n;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i].num);
        a[i].bh = i;
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&b[i].num);
        b[i].bh = i;
    }
    sort(a+1,a+1+n,cmp);
    sort(b+1,b+1+n,cmp);
    for(int i=1;i<=n;i++)c[b[i].bh] = a[i].bh;
    mergesort(1,n);
    cout << sum%mod << endl;
     return 0;
}

 

标签:4877,移动,int,mid,最小,++,火柴,归并,排序
From: https://www.cnblogs.com/jyssh/p/17636359.html

相关文章

  • Python 实现排序算法
    常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。冒泡排序冒泡排序(BubbleSort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复......
  • 4866: 瑞士轮 归并排序
    描述  2*N名编号为1~2N的选手共进行R轮比赛。每轮比赛开始前,以及所有比赛结束后,都会按照总分从高到低对选手进行一次排名。选手的总分为第一轮开始前的初始分数加上已参加过的所有比赛的得分和。总分相同的,约定编号较小的选手排名靠前。每轮比赛的对阵安排与该轮比赛开始前......
  • 5708: 逆序对 归并排序
    描述  给定 一个序列,求其逆序对的总数。所谓逆序对是指:序列a中存在两个元素a[i]和a[j],满足 i<j 且a[i]>a[j],则a[i]和a[j]为一个逆序对。  输入  第一行为正整数n(n<=100000)。第二行有n个正整数,最大不超过1000000。  输出  输出逆序对的总数。......
  • Java中List排序的4种方法
    在开发ERP或电商系统中,经常会遇到内容加密,生成签名,展示页面列表等功能场景,这个时候我们需要在Java程序中对List集合进行排序操作。排序的常见方法有以下4种:使用Comparable进行排序;使用Comparator进行排序;JDK8以上的环境,可以使用Stream流进行排排序;JD......
  • 冒泡排序
    冒泡排序-时间复杂度为O(n2)publicclassDemo{publicstaticvoidmain(String[]args){int[]a={3,23,12,3,423,22,4,534,66,34};System.out.println(Arrays.toString(sort(a)));}//冒泡排序//1比较数组中,两个相邻的元素,如......
  • 计数排序(Python)
    defcounting(data):"data里的value作为计数数组counts的index,然后把counts的value转换成data的index"#计数列表,存储每个值有多少个,以data的值作为索引,所以数组长度以最大值+1为准counts=[0foriinrange(max(data)+1)]#同时给数组赋初值0,等会逐个计数......
  • MySQL8.0 JSON的对比、排序和索引
    (目录)JSON的对比和排序JSON值可以通过=,<,<=,>,>=,<>,!=,<=>操作符来进行对比JSON不支持BETWEEN,IN(),GREATEST(),LEAST(),可以通过将JSON转换为其他数据类型来使用这些操作符。JSON值的对比在两个级别上进行,先进行数据类型的对比,如果类型相同,再进行值的对比。类型可以......
  • 冒泡排序
    #include<iostream>usingnamespacestd;intmain(){intn;cin>>n;inta[n];for(inti=0;i<n;i++){ cin>>a[i]; }for(inti=1;i<n;i++){for(intj=1;j<=n-i;j++){if(a[j-1]<a[j]){......
  • 基数排序
    博客地址:https://www.cnblogs.com/zylyehuo/#-*-coding:utf-8-*-#O(n)O(kn)#NBO(nlogn)importrandomdefpartition(li,left,right):tmp=li[left]whileleft<right:whileleft<rightandli[right]>=tmp:#从右面找比tmp小的数......
  • 【数据结构】排序2 交换排序
    交换排序就是基于比较交换的排序。主要讲两种交换排序算法:冒泡排序和快速排序。冒泡排序比较简单一般不会单独考察,重点考察的是快速排序的内容。1.冒泡排序基本算法思想:对于每趟排序,从后往前两两比较,如果为逆序则进行交换,这样很显然不能一趟就得到正确的序列,但是每次都会把最......