NOIP2013提高组 T2 火柴排队
一开始看也想不到这居然要用到逆序对,归并排序。
先来看看题目:
涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2
其中 ai 表示第一列火柴中第 i 个火柴的高度,bi 表示第二列火柴中第 i 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。
样例输入:
样例输出:
根据样例,设第二行的数为a{1,3,4,2},第三行的数为b{1,7,2,4}。对于题目要求通过交换使得两列火柴之间的的距离最小,满足这个要求只能使a中高度最小的火柴和b中高度最小的火柴搭配,第二小的和第二小的搭配。为了方便处理和后续的操作,把a和b进行离散化。离散化后,a{1,3,4,2},b{1,4,2,3}(离散化详解在*1)。遍历数组a,查找a[i]在数组b中所对应的位置(详细处理在*2)(需要用二分查找*3),存入新数组R,处理后为R{1,4,2,3},R[i]即为a[i]将要移到的位置,最小交换的次数正是R的逆序对数量。a中的3要移到R中3的位置,需要向右交换两次。相同的,可以这样认为,R中的3要向左移到a中的3的位置,则需要两次交换。R中3(即R[4])的逆序对数量为2,整个R的逆序对数量也为2。所求最少交换次数就是R的逆序对数量。使用归并排序。
时间复杂度(大概):O(7*(n log n)) 离散化:4*(n log n) ( 4次快排) 预处理二分查找+二分查找:2*(n log n) 归并排序:(n log n) 绝对不会超时qwq
*1:离散化前:a{1,3,4,2},b{1,7,2,4},给每个数组的每一个数标上序号,按照数组内容带上序号一起排序,重新编号,再根据之前标上的序号排回来恢复原状。
原始状态:
a | 1 | 3 | 4 | 2 |
序号 | 1 | 2 | 3 | 4 |
b | 1 | 7 | 2 | 4 |
序号 | 1 | 2 | 3 | 4 |
按照数组内容排序:
a | 1 | 2 | 3 | 4 |
序号 | 1 | 4 | 2 | 3 |
b | 1 | 2 | 4 | 7 |
序号 | 1 | 3 | 4 | 2 |
重新编号:
a | 1 | 2 | 3 | 4 |
序号 | 1 | 4 | 2 | 3 |
b | 1 | 2 | 3 | 4 |
序号 | 1 | 3 | 4 | 2 |
按照序号重新排序恢复:
a | 1 | 3 | 4 | 2 |
序号 | 1 | 2 | 3 | 4 |
b | 1 | 4 | 2 | 3 |
序号 | 1 | 2 | 3 | 4 |
完成,a离散化后和原来一样是因为样例特殊,参考b的离散化过程就好了。
*2:a[i]在数组b中所对应的位置。首先列出数组。
a | 1 | 3 | 4 | 2 |
b | 1 | 4 | 2 | 3 |
序号 | 1 | 2 | 3 | 4 |
R |
i=1的情况:a[i]为1,b中的1在b[1]中,b[1]对应的序号为1,所以R[i]为1,i=1,所以R[1]填上1。
i=2的情况:a[i]=3,b[4]=3,所以b中的3在b[4],对应序号为4。R[2]填上4
i=3:a[i]=4,b[2]=4,所以R[i]=2,R[3]填上2
i=4:a[i]=2,b[3]=2,所以R[4]=3
最终得R为:
R | 1 | 4 | 2 | 3 |
*3:如果查找a[i]在数组b中所对应的位置使用两重循环,则查找的时间复杂度为O(n^2),数据范围为n<=100000,光是查找就会超时,所以需要用二分排序。
贴上代码详细参考:
type
arr=array[..] of longint;
var
a1,b1,a,r:arr;
n,i,j:longint;
left,right,mid:longint;
ans:qword;
procedure qsort(var a,b:arr); //快排a数组,捆绑b数组
procedure sort(l,r: longint);
var
i,j,x,y: longint;
begin
i:=l;
j:=r;
x:=a[(l+r) div ];
repeat
while a[i]<x do
inc(i);
while x<a[j] do
dec(j);
if not(i>j) then
begin
y:=a[i];
a[i]:=a[j];
a[j]:=y;
y:=b[i];
b[i]:=b[j];
b[j]:=y;
inc(i);
dec(j);
end;
until i>j;
if l<j then
sort(l,j);
if i<r then
sort(i,r);
end;
begin
sort(,n);
end;
procedure mergesort(s,t:longint); //归并排序用来统计逆序对
var
mid,i,j,k:longint;
begin
if s=t then exit;
mid:=(s+t) div ;
mergesort(s,mid);
mergesort(mid+,t);
i:=s;
j:=mid+;
k:=s;
while (i<=mid) and (j<=t) do
if a[i]<=a[j] then
begin
r[k]:=a[i];
inc(i);
inc(k);
end
else
begin
r[k]:=a[j];
inc(j);
inc(k);
ans:=ans+(mid-i+); //逆序对
end;
while i<=mid do
begin
r[k]:=a[i];
inc(i);
inc(k);
end;
while j<=t do
begin
r[k]:=a[j];
inc(j);
inc(k);
end;
for i:=s to t do
a[i]:=r[i];
end;
begin
assign(input,'match.in');
assign(output,'match.out');
reset(input);
rewrite(output);
readln(n);
for i:= to n do
begin
read(a1[i]); //读入a数组
r[i]:=i; //编号
end;
qsort(a1,r); //按照数组内容排序
for i:= to n do a1[i]:=i; //重新编号 {离散化}
qsort(r,a1); //按照编号排序复原
readln;
for i:= to n do
begin
read(b1[i]); //读入b数组
r[i]:=i; //编号
end;
qsort(b1,r); //按照数组内容排序
for i:= to n do b1[i]:=i; //重新编号 {离散化}
qsort(r,b1); //按照编号排序复原 {for i:=1 to n do //处理a[i]在数组b中所对应的位置,使用两重循环,n到达1000时就会超时,所以舍弃
for j:=1 to n do
if b1[i]=a1[j] then
begin
a[i]:=j;
break;
end; } for i:= to n do r[i]:=i;
qsort(a1,r); //按照内容排序
for i:= to n do //遍历每个b[i]查找在a中的位置(这里a和b交换了,所以是查找b[i]在a中的位置)
begin
left:=;
right:=n;
mid:=(left+right) div ;
while (a1[mid]<>b1[i]) and (left<=right) do //二分查找,时间复杂度O(n log n)
begin
if a1[mid]>b1[i] then right:=mid-
else left:=mid+;
mid:=(left+right) div ;
end;
a[i]:=r[mid]; //此处的a数组即为上面所讲的R数组
end;
ans:=;
fillchar(r,sizeof(r),);
mergesort(,n); //归并排序统计逆序对
writeln(ans mod ); //依照题意对99999997取模
close(input);
close(output);
end.
NOIP2013提高组 T2 火柴排队的更多相关文章
- 洛谷P1966 [NOIP2013提高组Day1T2]火柴排队
P1966 火柴排队 题目描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi) ...
- 【NOIP2013提高组】火柴排队
https://www.luogu.org/problem/show?pid=1966 Σ(ai-bi)2=Σai2+Σbi2-2Σai*bi,要使Σ(ai-bi)2最小,则需2Σai*bi最大. 由 ...
- 【NOIP】提高组2013 火柴排队
[题意]两列n个火柴,分别有高度ai和bi(同一列高度互不相同),每次可以交换一列中的两个相邻火柴,定义距离为∑(ai-bi)^2,求使距离最小的最少交换次数,n<=10^5. [算法]逆序对 ...
- NOIP2013 提高组 Day1
https://www.luogu.org/problem/lists?name=&orderitem=pid&tag=83%7C30 期望得分:100+100+100=300 实际得 ...
- NOIP2013普及组 T2 表达式求值
OJ地址:洛谷P1981 CODEVS 3292 正常写法是用栈 #include<iostream> #include<algorithm> #include<cmat ...
- [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路
[NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路 题目大意: 对于长度为\(n(n\le10^5)\)的非负数列\(A\),每次可以选取一个区间\(-1\).问将数列清零至少需要 ...
- noip2013 提高组
T1 转圈游戏 题目传送门 果不其然 第一题还是模拟题 一波快速幂解决问题 #include<cstdio> #include<cstring> #include<alg ...
- JZOJ2020年8月11日提高组T2 宝石
JZOJ2020年8月11日提高组T2 宝石 题目 Description 见上帝动了恻隐之心,天后也想显示一下慈悲之怀,随即从口袋中取出一块魔术方巾,让身边的美神维纳斯拿到后堂的屏风上去试试,屏风是 ...
- 【GDKOI2014】JZOJ2020年8月13日提高组T2 石油储备计划
[GDKOI2014]JZOJ2020年8月13日提高组T2 石油储备计划 题目 Description Input Output 对于每组数据,输出一个整数,表示达到"平衡"状态 ...
随机推荐
- TortoiseSVN新人使用指南
http://blog.csdn.net/maplejaw_/article/details/52874348
- vue 开发和生产的跨域问题
开发阶段 在开发环境与后端调试的时候难免会遇到跨域问题,在 vue 项目中常用的是 proxyTable,这个用起来很方便. 打开 config 文件夹下面的 index.js,找到 dev 开发模式 ...
- LeetCode 解题总结
1. 最长合法括号串 给定只包含'('和')'的字符串,找出最长合法括号串的长度. Example 1: Input: "(()" Output: 2 Explanatio ...
- 项目Alpha冲剂(3/10)
1.项目燃尽图 2.今日进度描述 项目进展 完成数据库和服务器的连接部分,完成了一些应用的基本功能. 问题困难 完成了服务器的成功配置,同时实现了客户端与服务器的连接 心得体会 进度有明显的变化,成员 ...
- linux常用基础命令(一)
Rz命令 rz命令本地上传文件到服务器: rz在弹出的框中选择文件,上传文件 sz命令 sz命令发送文件到本地: Sz文件名 例:将文件file1 Sz file1 Tomcat启动/关闭命令 比如t ...
- CRMEB系统开发文档
CRMEB系统开发文档 https://gitee.com/ZhongBangKeJi/CRMEB hibernate:学习文档https://blog.csdn.net/u013087513/art ...
- 设计模式 — 抽象工厂模式(Abstract Factory)
工厂模式已经分析了简单工厂模式和工厂方法模式.并且了解了工厂方法模式去简单工厂模式的延伸,工厂方法模式如果不把工厂类抽象的话,就是简单工厂模式.由前面两个工厂模式可以猜测出抽象工厂模式应该是这两种工厂 ...
- css3——border-image属性的用法
项目需求是实现鼠标移到按钮上时,下方显示一张渐变的三角图片,于是想到使用border-image来实现. 实现;//向外偏移10px,可使边框内部的内容不是那么紧凑border-image-repea ...
- HttpClient不必每次新建实例而RestSharp推荐新建实例的原因
https://stackoverflow.com/questions/49588205/should-restclient-be-singleton-or-new-for-every-request ...
- django.db.utils.OperationalError: cannot ALTER TABLE "servers_ecs" because it has pending trigger events
数据库:postgresql9.4 原因:这是因为数据库的字段原来可以为null,现在改变该字段为not null,而你的数据库有数据,而这些数据该字段已经为null