【刷题】洛谷 P1966 火柴排队
题目描述
涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2
其中 ai 表示第一列火柴中第 i 个火柴的高度,bi 表示第二列火柴中第 i 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。
输入输出格式
输入格式:
输入文件为 match.in。
共三行,第一行包含一个整数 n,表示每盒中火柴的数目。
第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。
第三行有 n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。
输出格式:
输出文件为 match.out。
输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果。
输入输出样例
【输入输出样例 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 ≤ 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 火柴排队的更多相关文章
- [NOIP2013提高&洛谷P1966]火柴排队 题解(树状数组求逆序对)
[NOIP2013提高&洛谷P1966]火柴排队 Description 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相 ...
- 洛谷——P1966 火柴排队&&P1774 最接近神的人_NOI导刊2010提高(02)
P1966 火柴排队 这题贪心显然,即将两序列中第k大的数的位置保持一致,证明略: 树状数组求逆序对啦 浅谈树状数组求逆序对及离散化的几种方式及应用 方法:从前向后每次将数插入到bit(树状数组)中, ...
- 洛谷 P1966 火柴排队 解题报告
P1966 火柴排队 题目描述 涵涵有两盒火柴,每盒装有 \(n\) 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: \(\s ...
- [洛谷P1966] 火柴排队
题目链接: 火柴排队 题目分析: 感觉比较顺理成章地就能推出来?似乎是个一眼题 交换的话多半会往逆序对上面想,然后题目给那个式子就是拿来吓人的根本没有卵用 唯一的用处大概是告诉你考虑贪心一波,很显然有 ...
- 洛谷p1966 火柴排队 (逆序对变形,目标排序
题目描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2 其中 ai 表示 ...
- 洛谷P1966 火柴排队 贪心+离散化+逆序对(待补充QAQ
正解: 贪心+离散化+逆序对 解题报告: 链接在这儿呢quq 这题其实主要难在想方法吧我觉得?学长提点了下说用贪心之后就大概明白了,感觉没有很难 但是离散化这里还是挺有趣的,因为并不是能很熟练地掌握离 ...
- 洛谷 P1966 火柴排队
题目描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为:∑(ai−bi)2 其中ai 表示 ...
- 洛谷 P1966 火柴排队 —— 思路
题目:https://www.luogu.org/problemnew/show/P1966 首先,一个排列相邻交换变成另一个排列的交换次数就是逆序对数: 随便画一画,感觉应该是排个序,大的对应大的, ...
- 洛谷——P1966 火柴排队
https://www.luogu.org/problem/show?pid=1966 题目描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列 ...
随机推荐
- R 语言-基础
R语言 1997年成为GNU项目 开源免费 R官方网址 www.r-project.org R是数据分析领域的语言小巧灵活,通过扩展包来增强功能绘图功能代码简单 开发环境R + RStudio 1.数 ...
- C# 获取汉字拼音首字母/全拼
最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精 本节探讨C#获取汉字拼音首字母的方法: 代码类东西, ...
- ssh无法登录,提示Connection closing...Socket close.
一.问题无法ssh直接连接到服务器 [C:\~]$ ssh 192.168.7.77 Connecting to ... Connection established. To escape to lo ...
- 【干货】YUM安装PHP 7版本后,增加phalcon框架的报错解决
目录 1.yum安装php 7.x版本,此处部署7.3版本 2.安装phalcon框架 2.1.PHP版本依赖关系 2.2.编译phalcon扩展模块 2.3.增加扩展文件 3.部署phalcon遇到 ...
- [UOJ#461]新年的Dog划分[二分图染色、二分]
题意 给你一张无向连通图,你并不知道有哪些边,你首先要回答这张图是否是二分图,如果是,回答这张图黑白染色过后的任意一个点集.你需要在2000次询问内找到结果,每次你可以询问原图中一个边集删掉后是否还连 ...
- [BZOJ4851][JSOI2016]位运算[矩阵快速幂]
题意 给定长度为 \(\rm |S|\) 的 \(\rm 01\) 串并将其倍长 \(k\) 次得到一个 \(\rm|S|\times k\) 位的二进制数 \(R\) ,求有多少种在 \([0,R- ...
- Java和C#基本类库的区别
java.lang java .net Boolean System.Boolean Byte System. Byte Character System.Char Class System.Type ...
- 结对编程--C语言子程序词法分析
一.问题描述 C语言小子集表的定义 2.设计单词属性值,各类表格(表示标识符表.常量表),单词符号及机内表示,采用标准输入和输出的方式.程序从键盘接收代码,遇到代码结束符"#"时结 ...
- ansible自动化工具安装和简单使用
ansible自动化工具安装和简单使用 1.安装 ansible依赖于Python 2.6或更高的版本.paramiko.PyYAML及Jinja2. 2.1 编译安装 解决依赖关系 # yum -y ...
- Docker原理探究
问题思考:-------------------------------------Docker浅显原理理解-------------------------------------P1. ubunt ...