题目: 灯塔LightHouse
简要描述: 等效成给定n个坐标,统计坐标轴上两点x y方向只差是同向的,n点的x y坐标不会有重叠.
思路:
1. 对n点循环遍历,对两点做差值,满足y x方向同时大于或小于,那么累计+1->题目中给定数量级10^6,
时间复杂度太大,O(n!),不可用
2. 先对x方向进行排序,再统计y方向的相对顺序,如果y方向的也是顺序的,那么这两点必然满足条件+1
3. 需进行两次排序,采用归并排序将时间复杂度降为nlogn
, 第一次对x方向上归并排序,第二次对y
方向上进行归并排序,同时对顺序对计数.
假设各级子序列的归并排序已经完成,只剩下A B两个区间,那么可以保证A中所有元素x都比B中元素小,
合并子序列的时候如果A[i]y方向小于B[j],那么j及j后所有元素都应该统计为顺序对中.
实现
1. 读入元素后进行两次归并排序
2. 归并排序双路合并函数中区分出x方向排序和y方向排序,y方向排序同时进行计数
3. 双路合并函数中如果动态分配存储空间用于临时存储数组,10%超时,改成全局数组后95%用例通过,
仍有5%不行,瓶颈应该还是数组for循环的赋值,没有想到啥办法.
代码
cpp
#include <stdio.h> struct points { int x; int y; }; // global bool isBeacon(points lighthouse1, points lighthouse2); void merge(int lo, int mi, int hi, int flag=1); void mergeSort(int lo, int hi, int flag=1); int irow = 0; long iTotalNum = 0; points pointsLocate[4000000] = {}; points B[4000000] = {}; void getInputNum() { scanf("%d", &irow); for(int i=0; i<irow; i++) { int temp1, temp2; scanf("%d %d", &temp1, &temp2); pointsLocate[i].x = temp1; pointsLocate[i].y = temp2; } } bool lower_x(points left, points right) { return (left.x < right.x); } bool lower_y(points left, points right) { return (left.y < right.y); } void merge(int lo, int mi, int hi, int flag) { //points *B = new points[mi-lo]; int lb = mi - lo; int j = lo; int i=0; for(; i<lb;) { B[i] = pointsLocate[j]; i++; j++; } int lc = hi-mi; points *A = &pointsLocate[lo]; points *C = &pointsLocate[mi]; if(flag == 1) { for(int i=0, j=0, k=0; j<lb || k<lc;) { if(j<lb && (lc <= k || lower_x(B[j], C[k]))) A[i++] = B[j++]; if(k<lc && (lb <= j || lower_x(C[k], B[j]))) A[i++] = C[k++]; } } else { for(int i=0, j=0, k=0; j<lb || k<lc;) { if(j<lb && (lc <= k || lower_y(B[j], C[k]))) { if(lower_y(B[j], C[k])) { iTotalNum += lc-k; // printf("%d-%d-%d\n", lo, hi, lc-k); } A[i++] = B[j++]; } else if(k<lc && (lb << j || lower_y(C[k], B[j]))) A[i++] = C[k++]; // iTotalNum += lb-j; } } //delete B; } //nlogn void mergeSort(int lo, int hi, int flag) { if(hi - lo < 2) return; int mi = (lo+hi) >> 1; mergeSort(lo, mi, flag); mergeSort(mi, hi, flag); merge(lo, mi, hi, flag); } int main() { #ifndef _OJ_ freopen("inputlight.txt", "r", stdin); #endif getInputNum(); mergeSort(0, irow, 1); mergeSort(0, irow, 2); printf("%ld\n", iTotalNum); return 0; } //n^2复杂度 bool isBeacon(points lighthouse1, points lighthouse2) { if(lighthouse1.x>lighthouse2.x && lighthouse1.y>lighthouse2.y) return true; if(lighthouse1.x<lighthouse2.x && lighthouse1.y<lighthouse2.y) return true; return false; }
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。