题目描述

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

其中 ai 表示第一列火柴中第 i 个火柴的高度,bi 表示第二列火柴中第 i 个火柴的高度。

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

输入输出格式

输入格式:

输入文件为 match.in。

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

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

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

输出格式:

输出文件为 match.out。

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

输入输出样例

输入样例#1:

【输入输出样例 1】
4
2 3 1 4
3 2 1 4
【输入输出样例 2】
4
1 3 4 2
1 7 2 4
输出样例#1:

【输入输出样例 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 ≤ 1,000;

对于 100%的数据,1 ≤ n ≤ 100,000,0 ≤火柴高度≤ maxlongint

题解

刚做完POJ上一道逆序对的题,然后来看这道题,居然误打误撞有了思路。

首先我们看数据,对于:

1 5 6 8

2 8 4 5

我们知道,对于每个序列,只有第一小和第一小搭配一起、第二小和第二小搭配一起……这样公式计算出来的总和才最小,所以我们不妨把两行数据离散化,方便我们思考,于是序列变成了这样:

1 2 3 4

1 4 2 3

那么下一步应该做什么呢?不着急,我们先来看另外一个例子:

1 2 4 3 5

1 2 3 4 5

这个例子我们一看就知道只要移动一次是吧,所以答案就是1,那么我们是怎么看出来的呢?首先每一行的1和2和5都已经两相搭配,并且在各序列的最前面或最后面,那么我们知道,对于每行序列,最前面或最后面如果有已经搭配好的,我们就可以不要管它了,程序中我们只要从最前面往后扫,如果不一样记录下位置,同理再从最后面往前扫一遍,我们只要管中间的一部分就可以了,因此之前的数据可以简化成这样:

2 3 4

4 2 3

接下来,我们以第二行为标准,就知道,我们的任务的实质就是要把一行数字2 3 4移动最少的次数变成4 2 3,很多人已经想到逆序对了,但我们还需要一个步骤:重新标号。既然我们以第二行为标准,那么我们就可以记录4的标准是1,2的标准是2,3的标准是3,使第二行序列变成1 2 3,那么第一行就变成了2 3 1,到这里,不就是最普通的求逆序对了吗?所以归并一下,就出答案了。

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAXN=+,mod=;
int n,Dis[MAXN],P[MAXN],Ans[MAXN],temp[MAXN],ans;
struct node{
int x;
int id;
};
node A[MAXN],B[MAXN];
inline void read(int &x)
{
int data=,w=;
char ch=;
while(ch!='-'&&(ch<''||ch>''))ch=getchar();
if(ch=='-')w=-,ch=getchar();
while(ch>=''&&ch<='')data=(data<<)+(data<<)+(ch^''),ch=getchar();
x=data*w;
}
inline int comp1(const node&i,const node&j)
{
return i.x<j.x;
}
inline int comp2(const node&i,const node&j)
{
return i.id<j.id;
}
inline void margesort(int left,int right)
{
if(left==right)return ;
int mid=(left+right)/;
margesort(left,mid);
margesort(mid+,right);
int i=left,j=mid+,k=left;
while(i<=mid&&j<=right)
{
if(Ans[i]<Ans[j])temp[k++]=Ans[i++];
else
{
temp[k++]=Ans[j++];
ans=(ans+mid-i+)%mod;
}
}
while(i<=mid)temp[k++]=Ans[i++];
while(j<=right)temp[k++]=Ans[j++];
for(register int p=left;p<=right;++p)Ans[p]=temp[p];
}
int main()
{
read(n);
for(register int i=;i<=n;++i)
{
read(A[i].x);A[i].id=i;
}
sort(A+,A+n+,comp1);
for(register int i=;i<=n;++i)
{
read(B[i].x);B[i].id=i;
}
sort(B+,B+n+,comp1);
for(register int i=;i<=n;++i)
{
A[i].x=i;B[i].x=i;
}
sort(A+,A+n+,comp2);
sort(B+,B+n+,comp2);
int pos=,head,tail;
for(register int i=;i<=n;++i)
{
if(A[i].x!=B[i].x)
{
head=i;
break;
}
}
for(register int i=n;i>=;--i)
{
if(A[i].x!=B[i].x)
{
tail=i;
break;
}
}
for(register int i=head;i<=tail;++i)
{
P[++pos]=A[i].x;
Dis[B[i].x]=pos;
}
for(register int i=;i<=pos;++i)Ans[i]=Dis[P[i]];
margesort(,pos);
printf("%d",ans%mod);
return ;
}

P1966 火柴排队

【刷题】洛谷 P1966 火柴排队的更多相关文章

  1. [NOIP2013提高&洛谷P1966]火柴排队 题解(树状数组求逆序对)

    [NOIP2013提高&洛谷P1966]火柴排队 Description 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相 ...

  2. 洛谷——P1966 火柴排队&&P1774 最接近神的人_NOI导刊2010提高(02)

    P1966 火柴排队 这题贪心显然,即将两序列中第k大的数的位置保持一致,证明略: 树状数组求逆序对啦 浅谈树状数组求逆序对及离散化的几种方式及应用 方法:从前向后每次将数插入到bit(树状数组)中, ...

  3. 洛谷 P1966 火柴排队 解题报告

    P1966 火柴排队 题目描述 涵涵有两盒火柴,每盒装有 \(n\) 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: \(\s ...

  4. [洛谷P1966] 火柴排队

    题目链接: 火柴排队 题目分析: 感觉比较顺理成章地就能推出来?似乎是个一眼题 交换的话多半会往逆序对上面想,然后题目给那个式子就是拿来吓人的根本没有卵用 唯一的用处大概是告诉你考虑贪心一波,很显然有 ...

  5. 洛谷p1966 火柴排队 (逆序对变形,目标排序

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

  6. 洛谷P1966 火柴排队 贪心+离散化+逆序对(待补充QAQ

    正解: 贪心+离散化+逆序对 解题报告: 链接在这儿呢quq 这题其实主要难在想方法吧我觉得?学长提点了下说用贪心之后就大概明白了,感觉没有很难 但是离散化这里还是挺有趣的,因为并不是能很熟练地掌握离 ...

  7. 洛谷 P1966 火柴排队

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

  8. 洛谷 P1966 火柴排队 —— 思路

    题目:https://www.luogu.org/problemnew/show/P1966 首先,一个排列相邻交换变成另一个排列的交换次数就是逆序对数: 随便画一画,感觉应该是排个序,大的对应大的, ...

  9. 洛谷——P1966 火柴排队

    https://www.luogu.org/problem/show?pid=1966 题目描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列 ...

随机推荐

  1. [Lydsy1805月赛]对称数 BZOJ5361

    分析: 这个题,还是蛮有趣的.考虑,如果l,r区间内的所有数出现奇数次,那么[l-1,r]的抑或和等于所得抑或和. 之后怎么维护呢,主席树维护区间抑或和,记得将每个点附上一个ull级别的随机数,之后抑 ...

  2. 20155209林虹宇Exp4 恶意代码分析

    Exp4 恶意代码分析 系统运行监控 使用schtasks指令监控系统运行 新建一个txt文件,然后将txt文件另存为一个bat格式文件 在bat格式文件里输入以下信息 然后使用管理员权限打开cmd, ...

  3. Git中使用amend解决提交冲突

    问题描述       场景:当你提交的时候,发现跟要合并的流有冲突,你需要解决完冲突再次提交. 如果在SVN时代,你可以直接在本地解决完冲突再提交就可以了,因为SVN会把正确的代码先提交到服务器,至于 ...

  4. 您需要来自XXX的权限才能对此文件夹进行更改

    解决办法: cmd命令:del/f/s/q 文件夹

  5. SpringBoot整合Mybatis之进门篇

    已经有好些日子没有总结了,不是变懒了,而是我一直在奋力学习springboot的路上,现在也算是完成了第一阶段的学习,今天给各位总结总结. 之前在网上找过不少关于springboot的教程,都是一些比 ...

  6. Scala基础(1)

    Scala基础语法 声明与定义: val,常量声明                       val  x:T(把x声明成一个类型为T的常量)  x是变量的名字,T是变量的类型          v ...

  7. pandas 初识(四)

    Pandas 和 sqlalchemy 配合实现分页查询 Mysql 并获取总条数 @api.route('/show', methods=["POST"]) def api_sh ...

  8. 学习 google file system 心得体会

    Google File system文件系统,是在特别便宜的普通硬件设备上运行,它是一个面向大规模数据密集型运用的.可伸缩的分布式文件系统. 与传统文件相比,它认为组件失效是很平常的事件,因为GFS包 ...

  9. BugPhobia准备篇章:Scrum Meeting工作分析篇

    特别说明:此博客不计入正式开发过程的Scrum Meeting篇章,只是工作的基础分析 前端 王鹿鸣.钱林琛撰写初稿 能否前端完成一个页面后就能在本地跑起来进行测试? 能否在前端和后端完成对接后单页面 ...

  10. 铁大快捷记账Alpha版使用说明书

    一. 引言 (1) 编写目的 (2) 参考资料 (3) 术语和缩写词 二. 网站概述 (1) 网站用途 (2) 网站运行 三. 网站使用过程 (1)网站登录 (2) 功能说明 一.引言 (1)编写目的 ...