NOIP 2013 火柴排队
洛谷 P1966 火柴排队
JDOJ 2227: [NOIP2013]火柴排队 D1 T2
Description
涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:∑i=1n(ai−bi)2,其中 ai 表示第一列火柴中第 i 个火柴的高度,bi 表示第二列火柴中第 i 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。
Input
共三行,第一行包含一个整数 n,表示每盒中火柴的数目。
第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。第三行有 n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。
Output
输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果。
Sample Input
Sample Input I: 4 2 3 1 4 3 2 1 4 Sample Input II: 4 1 3 4 2 1 7 2 4
Sample Output
Sample Output I: 1 Sample Output II: 2
HINT
【样例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 ≤火柴高度≤ 231 − 1。
Source
题解:
这是一道求逆序对的题目;
求逆序对的手段有的时候是次要的,我们首先要弄明白为什么这道题是求逆序对的题。
那么让我来概括一下题目大意:
让你把两列火柴排一下队,使得俩队列中序号相同的两根火柴的高度差值最小。
然鹅,最终要求的竟然不是最小差值,而是差值最终需要交换多少次//%%%
所以我们得出这个结论,这两列火柴必须是最大匹配最大,次大匹配次大,以此类推,才能得出最小差值。
再看看题目中要求只能交换相邻的两个火柴的位置,所以我们想到了求逆序对个数。
那么我们开始回头看逆序对咋求。
1、归并排序
2、树状数组
3、暴力(想到这种方法的当场打死)
都挺简单的,因为我是在树状数组板块中学的逆序对,所以我使用了树状数组求逆序对。
如果通过逆序对本身的定义来理解的话,我们会发现:这个逆序对不应该用树状数组求啊?但是人类的智力是无极限的,我们回顾一下树状数组的用途,发现这个玩意是用来区间求和的,也就是说,这个东西只能裸的求和?
那未免太辱没它的名头了。
我们这样想,树状数组在求逆序对的时候只是一个求和的工具,我们可以通过树状数组来求当前这个数所在位置前面比它大的数的个数,就可以方便的统计逆序对的个数。
所以我们考虑把每个火柴定义一个结构体,一个存编号,也就是位置,一个存长度。最后我们按照长度由小到大排序(当然由大到小也可以),最后我们进行整个程序也是思路中最重要的点:离散化。
简单介绍一下离散化。这算是一种常用的小技巧,适用于什么情况呢?就是我们在解题过程中只在意这个数的大小关系,而不在意这个数到底是多大。我们可以形象地理解一下,现在有5个数分布在1-10000000的区间内,我们只需要知道他们到底多大,所以我们建一个离散化数组D[],其中D[i]表示第i个元素在其中排第j位,这个j最大也只是5.
这个过程就叫做离散化。
显然这道题适用离散化。
所以我们将数据离散化之后,就可以进行树状数组的处理,其中树状数组函数getsum(sum[i])就表示比高度为i的元素大的数的个数。
然后统计ans的时候要记得ans+=i-getsum(sum[i]);表示当前位置减去比当前位置大的所有元素的个数。
注意每次操作的时候都取模。
AC code:
#include<cstdio>
#include<algorithm>
#define mod 99999997
using namespace std;
struct node
{
int h,order;
}a[100010],b[100010];
int c[100010],sum[100010],n,ans;
bool cmp(node a,node b)
{
return a.h<b.h;
}
void fix(int x)
{
for(int i=x;i<=n;i+=i&-i)
c[i]++,c[i]%=mod;
}
int getsum(int x)
{
int ret=0;
for(int i=x;i;i-=i&-i)
ret+=c[i],ret%=mod;
return ret;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].h);
a[i].order=i;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
{
scanf("%d",&b[i].h);
b[i].order=i;
}
sort(b+1,b+n+1,cmp);
for(int i=1;i<=n;i++)
sum[a[i].order]=b[i].order;
for(int i=1;i<=n;i++)
{
fix(sum[i]);
ans+=i-getsum(sum[i]);
ans%=mod;
}
printf("%d",ans);
return 0;
}
NOIP 2013 火柴排队的更多相关文章
- 【NOIP】提高组2013 火柴排队
[题意]两列n个火柴,分别有高度ai和bi(同一列高度互不相同),每次可以交换一列中的两个相邻火柴,定义距离为∑(ai-bi)^2,求使距离最小的最少交换次数,n<=10^5. [算法]逆序对 ...
- Codevs 3286 火柴排队 2013年NOIP全国联赛提高组 树状数组,逆序对
题目:http://codevs.cn/problem/3286/ 3286 火柴排队 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : ...
- NOIP 2013 T2 火柴排队 ---->求逆序对
[NOIP2013T2]火柴排队 背景 noip2013day1 描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各 自 排成一列, 同一列火柴的高度互不相同, ...
- NOIP 2013 货车运输【Kruskal + 树链剖分 + 线段树 】【倍增】
NOIP 2013 货车运输[树链剖分] 树链剖分 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在 ...
- NOIP 2013
Prob.1 转圈游戏 找到循环节,然后快速幂.代码: #include<cstdio> #include<cstring> #include<iostream> ...
- 洛谷P1966 【火柴排队】
题解 P1966 [火柴排队] 说明: 在数学中有个公式: (a1-b1)^2+(a2-b2)^2<(a2-b1)^2+(a1-b2)^2 (你可以自己试着证一下) 两列火柴对应的两根火柴在各列 ...
- [树状数组+逆序对][NOIP2013]火柴排队
火柴排队 题目描述 涵涵有两盒火柴,每盒装有n根火柴,每根火柴都有一个高度.现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:∑ (ai-bi)2,i=1,2,3,. ...
- Luogu 1979 NOIP 2013 华容道(搜索,最短路径)
Luogu 1979 NOIP 2013 华容道(搜索,最短路径) Description 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面 ...
- noip 2013 提高组 day1
1.转圈游戏: 解析部分略,快速幂就可以过 Code: #include<iostream> #include<fstream> using namespace std; if ...
随机推荐
- 【ASP.NET Core分布式项目实战】(五)Docker制作dotnet core控制台程序镜像
Docker制作dotnet core控制台程序镜像 基于dotnet SDK 新建控制台程序 mkdir /home/console cd /home/console dotnet new cons ...
- FontForge 汉化教程
引用 :http://www.sucaijishi.com/2018/articles_0815/258.html FontForge是一款免费字库编辑工具,官方暂不提供简体中文,本文汉化方法在201 ...
- Java连载13-整数型字面值的强制转换
一.注意点 1.大容量不能直接赋值给小容量:大容量转化为小容量需要进行,强制类型转换,强制类型转换需要加上“强制类型转换符”,加上强制类型转换符之后编译通过了但是精度会有有可能损失.所以强制类型转换要 ...
- FFT(快速傅里叶变换)
FFT(快速傅里叶变换) 前置知识 \(1.复数\) \(2.单位根\) \(3.循环结构\) \(4.C++\) 1.复数 \(定义:形如a+bi的数,其中i^2=-1\) \(计算:1.(a+bi ...
- Linux系统安装snmp服务
Linux安装snmp详解 Snmp一种网络之间的传输协议,通过snmp可以采集很多指标比如cpu.内存及磁盘的信息,现在越来越多的网络设备基本上都支持snmp,本文介绍了snmp的安装过程. 二.安 ...
- pom.xml管理jar包——安全性框架配置文件
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> &l ...
- Bootstrap初始化过程源码分析--netty客户端的启动
Bootstrap初始化过程 netty的客户端引导类是Bootstrap,我们看一下spark的rpc中客户端部分对Bootstrap的初始化过程 TransportClientFactory.cr ...
- 基于wince系统开发的 SQLServe Mobile数据库应用
SQLServe Mobile数据库以前的版本是SQLServe CE,现在最新的是3.5的版本,最近用vs2008做了一个小程序,是对SQLServe Mobile数据库读写数据. 注:SQLSer ...
- JavaScript中的类方法、对象方法、原型方法
类方法:也叫函数方法,在JavaScript中函数也是一个对象,所以可以为函数添加属性以及方法: 对象方法:包括构造函数中的方法以及其原型上面的方法: 原型方法:一般用于对象实例共享,在原型上面添加该 ...
- sigaction信号处理
1. sigaction int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); signu ...