LightHouse/归并排序
生活随笔
收集整理的這篇文章主要介紹了
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/归并排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java面试题之Oracle 支持哪三种
- 下一篇: 个人交社保一个月要交多少钱