【C++實現】LightHouse
阿新 • • 發佈:2019-01-30
燈塔(LightHouse)
描述
海上有許多燈塔,為過路船隻照明。
(圖一)
如圖一所示,每個燈塔都配有一盞探照燈,照亮其東北、西南兩個對頂的直角區域。探照燈的功率之大,足以覆蓋任何距離。燈塔本身是如此之小,可以假定它們不會彼此遮擋。
(圖二)
若燈塔A、B均在對方的照亮範圍內,則稱它們能夠照亮彼此。比如在圖二的例項中,藍、紅燈塔可照亮彼此,藍、綠燈塔則不是,紅、綠燈塔也不是。
現在,對於任何一組給定的燈塔,請計算出其中有多少對燈塔能夠照亮彼此。
輸入
共 n + 1 行。
第 1 行為 1 個整數 n,表示燈塔的總數。
第 2 到 n + 1 行每行包含 2 個整數 x, y,分別表示各燈塔的橫、縱座標。
輸出
共 1 行
一個整數,表示可照亮彼此的燈塔對的數量。
樣例
輸入(如圖2所示)
3
2 2
4 3
5 1
輸出
1
限制
對於 90% 的測例:1 ≤ n ≤ 1,000,000
全部測例:1 ≤ n ≤ 3,000,000
燈塔的座標 x, y是整數,且不同燈塔的 x, y座標均互異
1 ≤ x, y ≤ 10^8
思路:
按x座標歸併排序,
再按y座標歸併排序,同時記錄逆序對個數cnt+=lb-j
#define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; long long int cnt = 0; struct point { int x; int y; }; point *v; void merge(int lo, int mi, int hi) { int lb = mi - lo; int lc = hi - mi; point *A = v + lo; point *B = new point[lb]; point *C = v + mi; for (size_t i = 0; i < lb; i++) { B[i]= A[i]; } for (int i = 0, j = 0, k = 0; (j < lb || k < lc);) { if (j < lb && (k >= lc || B[j].x<=C[k].x)) { A[i++] = B[j++]; } if (k<lc && (j >= lb || B[j].x>C[k].x)) { A[i++] = C[k++]; } } delete[] B; } void mergeSort(int lo, int hi) { if (hi - lo < 2) return; int mi = (hi + lo) >> 1; mergeSort(lo, mi); mergeSort(mi, hi); merge(lo,mi,hi); } void revMerge(int lo, int mi, int hi) { int lb = mi - lo; int lc = hi - mi; point *A = v + lo; point *B = new point[lb]; point *C = v + mi; int tmp; for (size_t i = 0; i < lb; i++) { B[i] = A[i]; } for (int i = 0, j = 0, k = 0; (j < lb || k < lc);) { if (j < lb && (k >= lc || B[j].y <= C[k].y)) { A[i++] = B[j++]; } if (k<lc && (j >= lb || B[j].y>C[k].y)) { A[i++] = C[k++]; if (j < lb) { cnt+=lb-j; } } } delete[] B; } void revSort(int lo, int hi) { if (hi - lo < 2) return; int mi = (hi + lo) >> 1; revSort(lo, mi); revSort(mi, hi); revMerge(lo, mi, hi); } long long int div(int e) { if (e == 2) return 2; if (e == 1) return 1; return e*div(e - 1); } int main() { setvbuf(stdin, new char[1 << 20], _IOFBF, 1 << 20); // 設定I/O緩衝區,加速讀寫 int n, tmpx, tmpy; scanf("%d", &n); if (n == 1) return 0; v = new point[n](); for (size_t i = 0; i < n; i++) { scanf("%d%d",&v[i].x,&v[i].y); } mergeSort(0, n); /*cout << "---"; for (size_t i = 0; i < n; i++) { cout << v[i].x <<" "<< v[i].y << endl; }*/ if (n == 2) return v[0].y <= v[1].y ? 1 : 0; revSort(0, n); //cout << cnt << endl; cout << n*(n-1) / 2 - cnt; system("pause"); return 0; } /* 9 4 7 5 9 3 6 2 8 1 2 7 1 8 5 6 4 9 3 */