题目描述

涵涵有两盒火柴,每盒装有 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

这个题贪心的证明

假设第一列有两个数 a,b(a < b) 第二列有两个数 x,y(x < y)

那么看(a-x)^2+(b-y)^2与(a-y)^2+(b-x)^2哪个更小,哪个就更优

可以假设左边<右边,然后化简,将两边的二次方都去掉

化简后得 -ax-by < -ay-bx

再次移项得到 a(x-y)>b(x-y) 由于x-y是负数,化简后得 a < b,式子成立(意思就是如果左边>右边的话就与条件矛盾了)

那么显然小的配小的,大的配大的最优

那么我们目标就是a的第一大和b的第一大在一块,a的第i大和b的第i大在一块

那么我们可以固定一端移动另外一端,

固定a移动b,那么我们发现移动的时候按b的第几大为关键字进行移动,那么值为1的数不一定要移动到1这个位置

因为1这个下标索引不一定是a的第一大

所以我们发现一个显然成立的事实,那就是从一个乱序数组排序成有序数组的最少交换次数和一个有序数组还原成乱序数组的最小交换次数相同

那么就相当于,当前已经按目标位置排好序的序列到原位置的最少交换次数=原序列到各自移动到目标位置的序列的最少交换次数

因为等式右边难于实现,所以选择等价的左边的实现,先让他跑到应该到的位置,然后跑回原位,这就是解决方法(有点像时光倒流哦

附上代码 (套自己的模板所以有点长

 1 #include <iostream>
2 #include <cstdio>
3 #include <algorithm>
4 #include <cstring>
5 using namespace std;
6 const int maxn=1e5+7;
7 int N,w;
8 typedef long long ll;
9 ll t[maxn],q[maxn];
10 struct node{
11 int id,v;node(){};node(int id,int v):id(id),v(v){};
12 };
13 node a[maxn],b[maxn];
14 int lowbit(int x){
15 return x&-x;
16 }
17 void add(int n,int x){
18 while(n<=N){
19 t[n]+=x;
20 n+=lowbit(n);
21 }
22 }
23 ll sum(int n){
24 ll ans=0;
25 while(n){
26 ans=(ans+t[n]);
27 n-=lowbit(n);
28 }
29 return ans;
30 }
31 bool cmp1(node a,node b){
32 return a.v<b.v;
33 }
34 bool cmp2(node a,node b){
35 return a.id<b.id;
36 }
37 int main(){
38 int n,x;scanf("%d",&n);
39 for(int i=1;i<=n;++i){
40 scanf("%d",&x);
41 a[i]=node(i,x);
42 }
43 for(int i=1;i<=n;++i){
44 scanf("%d",&x);
45 b[i]=node(i,x);
46 }
47 sort(a+1,a+1+n,cmp1);
48 sort(b+1,b+1+n,cmp1);
49 int cnt=1,st=1,pre=a[1].v;
50 for(int i=2;i<=n;++i){
51 while(i<=n&&a[i].v==pre) i++;
52 for(int j=st;j<i;++j){
53 a[j].v=cnt;
54 }
55 st=i;pre=a[i].v;
56 cnt++;
57 }
58 for(int j=st;j<=n;++j) a[j].v=cnt;
59 //for(int i=1;i<=n;++i) printf("%d,",a[i].v);printf("\n");
60 cnt=1,st=1,pre=b[1].v;
61 for(int i=2;i<=n;++i){
62 while(i<=n&&b[i].v==pre) i++;
63 for(int j=st;j<i;++j){
64 b[j].v=cnt;
65 }
66 st=i;pre=b[i].v;
67 cnt++;
68 }
69 for(int j=st;j<=n;++j) b[j].v=cnt;
70 //for(int i=1;i<=n;++i) printf("%d,",b[i].v);printf("\n");
71 //sort(a+1,a+1+n,cmp2);sort(b+1,b+1+n,cmp2);
72 N=n;
73 for(int i=1;i<=n;++i){
74 q[a[i].id]=b[i].id;//也就是说,当前排名相同的两个位置,b[i].id的目标位置是a[i].id,
75 }
76 ll ans=0;
77 for(int i=n;i>=1;--i){
78 ans=(ans+sum(q[i]-1))%99999997;
79 add(q[i],1);
80 }
81 printf("%lld\n",ans);
82 return 0;
83 }

为什么按值排序呢,因为我们要对排名相同的配对,这是我们要的目标序列

最新文章

  1. CSharpGL(40)一种极其简单的半透明渲染方法
  2. 【代码笔记】iOS-时间选择框
  3. BINARY SEARCH in read table statement
  4. mongoDB索引使用
  5. CodeForces 602E【概率DP】【树状数组优化】
  6. Nginx 内置全局变量
  7. 笔记- iphone手机音频AAC视频H264推流(一) iphone手机推流最佳方案
  8. ORA-00054:资源正忙,要求指定NOWAIT
  9. python成长之路15
  10. VR全景智慧城市—城市就在你眼前
  11. AC自动机讲解
  12. 数据库sql语句常见面试题
  13. Neovim中提示Error: Required vim compiled with +python
  14. CSDN不登录阅读全文(最新更新
  15. 小程序 青少儿书画 利用engineercms作为服务端
  16. 使用php与mysql构建我们的网站
  17. python字符串前面加u,r,b的含义
  18. 牛客网 PAT 算法历年真题 1012 : D进制的A+B (20)
  19. HttpServletRequest解决中文乱码的问题
  20. NodeJS框架express的路径映射(路由)功能及控制

热门文章

  1. 迈凯伦765LT/600LT/720S/650S/570S维修手册电路图Mclaren车间手册接线图
  2. 面试常问的ArrayQueue底层实现
  3. uni-app开发经验分享八: 实现微信APP支付的全过程详解
  4. 面试官:你说说ReentrantLock和Synchronized区别
  5. 三. SpringCloud服务注册与发现
  6. libco hook原理简析
  7. 洛谷P2292
  8. 洛谷P2573
  9. 济南学习D3T1__线性筛和阶乘质因数分解
  10. koa2+koa-generator+mysql快速搭建nodejs服务器