LightHouse/归并排序
灯塔(LightHouse)
题目见https://dsa.cs.tsinghua.edu.cn/oj/problem.shtml?id=1144
最近复习DSA,便在看邓老师的mooc,顺便做做配套的题目,挺有意思的。
一、题目分析
简述思路:两次排序,第一次是对结构体的x坐标进行排序,第二次是计数y坐标中的逆序对/顺序对的数目。
第一次排序可以采用快速排序/归并排序等
第二次就是归并排序计算逆序对数目
注意点如下:
- 数据范围大小,合适的地方需要使用
long long
,注意n*n
结果范围可能超过int,此时也需要long long n;
- new和delete需要配合使用。
int* B=new int[lenB];...delete[] B;
否则会造成内存泄漏,oj显示MLE - 归并排序的归并部分写法,最优写法如下
for(int i=0,j=0,k=0;i<lenB;){if(j>=lenC||B[i]<C[j]){A[k++]=B[i++];if(j<lenC)count+=(lenC-j);//顺序对在这里出现}if(j< lenC&&C[j]<=B[i]){A[k++]=C[j++];//这里其实是逆序对}
}
逆序对计数在归并过程中自然进行即可,无需提前对B/C数组做二分查找。
二、代码实现
#include<cstdio>
#define MAX_NUM 4000006
typedef long long ll;
struct point{int x;int y;
};point origin[MAX_NUM];
int arr[MAX_NUM];
ll count;//顺序对数目void MergeSort_X(point* p,int lo,int hi);
void MergeSort_Y(int* p,int lo,int hi);
void Merge_X(point* p,int lo,int mi,int hi);
void Merge_Y(int* p,int lo,int mi,int hi);int main(){int n;scanf("%d",&n );for(int i=0;i<n;i++){scanf("%d%d", &origin[i].x,&origin[i].y);}MergeSort_X(origin,0,n);//将origin数组按照X坐标升序排列for(int i=0;i<n;i++){arr[i]=origin[i].y;}MergeSort_Y(arr,0,n);//计算Y坐标中顺序对的数目printf("%lld",count);
}//对数组p[lo,mi)按X坐标进行升序排序
void MergeSort_X(point* p,int lo,int hi){if(hi-lo<2)return;int mi=(lo+hi)/2;MergeSort_X(p,lo,mi);MergeSort_X(p,mi,hi);Merge_X(p,lo,mi,hi);
}//对数组p[lo,mi)和数组p[mi,hi)进行归并
void Merge_X(point* p,int lo,int mi,int hi){point* A=p+lo;int lenB=mi-lo;//p[lo,mi)int lenC=hi-mi;//p[mi,hi)point* B=new point[lenB];for(int i=0;i<lenB;i++){B[i]=A[i];}point* C=p+mi;for(int i=0,j=0,k=0;i<lenB;){if(j>=lenC||B[i].x<=C[j].x)A[k++]=B[i++];if(j< lenC&&C[j].x< B[i].x)A[k++]=C[j++];}delete[] B;
}void MergeSort_Y(int* p,int lo,int hi){if(hi-lo<2)return;int mi=(lo+hi)/2;MergeSort_Y(p,lo,mi);MergeSort_Y(p,mi,hi);Merge_Y(p,lo,mi,hi);
}void Merge_Y(int* p,int lo,int mi,int hi){int* A=p+lo;int lenB=mi-lo;int lenC=hi-mi;int* B=new int[lenB];int* C=p+mi;for(int i=0;i<lenB;i++){B[i]=A[i];}for(int i=0,j=0,k=0;i<lenB;){if(j>=lenC||B[i]<C[j]){A[k++]=B[i++];if(j<lenC)count+=(lenC-j);//顺序对在这里出现}if(j< lenC&&C[j]<=B[i]){A[k++]=C[j++];//这里其实是逆序对}}delete[] B;
}
转载于:https://www.cnblogs.com/cbw052/p/10467246.html
LightHouse/归并排序相关推荐
- 分治算法的设计思想(二分检索、二分归并排序)
分治策略思想: 将原问题划分或者归结为规模较小的子问题. 递归或迭代求解每一个问题. 将子问题的解综合得到原问题的解. 性质: 子问题与原问题具有相同的性质. 子问题的求解彼此独立. 划分时子问题的规 ...
- 归并排序(代码注释超详细)
归并排序: (复制粘贴百度百科没什么意思),简单来说,就是对数组进行分组,然后分组进行排序,排序完最后再整合起来排序! 我看了很多博客,都是写的8个数据呀什么的(2^4,分组方便),我就想着,要是10 ...
- 递归/分治:归并排序
前言 分治算法: 将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同.求出 子问题的解后进行合并,就可得到原问题的解. 步骤如下: 分解,将要解决的问题划分成若 干规 ...
- C语言 带比较器的归并排序
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 typedef int DataType; 5 6 //比较器 7 int myc ...
- github pages_使用GitHub Pages和Lighthouse增强您的开发人员产品组合
github pages For someone who is trying to break into software development, it doesn't matter where y ...
- (C++)归并排序的递归与非递归实现
递归实现 merge函数利用的是双指针技巧降低复杂度. mergeSort函数使用了递归,当中先对左右序列各调用一次mergeSort,再对整个序列调用merge.就按照最浅层的归并的思想去理解,不要 ...
- 排序算法java版,速度排行:冒泡排序、简单选择排序、直接插入排序、折半插入排序、希尔排序、堆排序、归并排序、快速排序...
先推荐一篇关于排序算法的文章:http://www.cppblog.com/guogangj/archive/2009/11/13/100876.html 本文思路部分来源于上篇文章,但测得的结果似乎 ...
- Ultra-QuickSort POJ 2299(归并排序)
http://acm.hust.edu.cn/vjudge/contest/124435#problem/D 题意:给出一个长度为n的数列,你每一次可以随意交换其中两个数字的位置.问你至少交换几次,才 ...
- 【算法导论】【ACM】归并排序总结
许多有用的算法在结构上是递归的:为了解决一个给定的问题,算法一次或多次递归地调用其自身以解决紧密相关地若干子问题.这些算法典型的遵循分治法地思想:将原问题分解成几个规模较小但类似于原问题的子问题,递归 ...
最新文章
- linux g 手动安装,linux上oracle11g 手动安装
- 绩效C,看不到希望...
- SAP WM 二步法确认TO单据
- ios开发 静音键设置_iOS开发,改变系统铃声音量和静音,并非媒体播放音量
- python中range和xrange的异同
- Git 重置reset,检出checkout和回滚revert(reverse)有什么区别?
- 使用Raphael实现html中绘图
- 按钮点击打开新页面_PDF怎么打开?如何制作一个PDF格式的文档?
- 2017.3.12 每日小记
- Linux系统中的CPU利用率
- golang range循环内部
- linux安装mvn及nexus远程仓库
- trim去除空格失败
- python(模块)xlsxwriter
- 光纤通信是不是计算机类的,光纤通信专业属于什么门类
- Java实验一 Java编程基础
- 基于SSH开发service电子信箱(邮箱)管理系统
- python excel画图_matplotlib 画图直接写入excel
- 华东师大在职计算机分数线,报考华东师范大学在职研究生分数线是多少呢?
- 家用计算机的发展历史,计算机发展简史