As shown in the following figure, If another lighthouse is in gray area, they can beacon each other.node
For example, in following figure, (B, R) is a pair of lighthouse which can beacon each other, while (B, G), (R, G) are NOT.數組
1st line: Nide
2nd ~ (N + 1)th line: each line is X Y, means a lighthouse is on the point (X, Y).spa
How many pairs of lighthourses can beacon each othercode
( For every lighthouses, X coordinates won't be the same , Y coordinates won't be the same )blog
Input排序
3 2 2 4 3 5 1
Outputip
1
For 90% test cases: 1 <= n <= 3 * 105get
For 95% test cases: 1 <= n <= 106string
For all test cases: 1 <= n <= 4 * 106
For every lighthouses, X coordinates won't be the same , Y coordinates won't be the same.
1 <= x, y <= 10^8
Time: 2 sec
Memory: 256 MB
The range of int is usually [-231, 231 - 1], it may be too small.
解題思路:將燈塔按照x軸由大到小排序,即將問題轉化爲求y的逆序對的個數。求解逆序對能夠利用歸併排序的思路實現。
以下圖:在某次歸併的時候,左右兩個數組已經排好順序,若是遇到a[i] > a[j],則,a[j] 與a[i] 到a[n]的全部元素均構成逆序對。
在歸併排序的時候順便統計一下逆序對的個數。
注意,要統計的逆序對個數可能很大。
代碼以下
#include<cstdio> #include<cstring> #define MAXN 4000005 #define ll long long using namespace std; struct node{ ll x; ll y; } tower[MAXN]; ll des[MAXN]; struct node des1[MAXN]; int N; ll num; void merg(int l, int mid, int r) { int i, j; int k; i = l; k = l; j = mid + 1; while(i <= mid && j <= r){ if(tower[i].x < tower[j].x){ des1[k].x = tower[i].x; des1[k++].y = tower[i++].y; } else{ des1[k].x = tower[j].x; des1[k++].y = tower[j++].y; } } while(i <= mid){ des1[k].x = tower[i].x; des1[k++].y = tower[i++].y; } while(j <= r){ des1[k].x = tower[j].x; des1[k++].y = tower[j++].y; } for (i = l; i <= r; i++){ tower[i].x = des1[i].x; tower[i].y = des1[i].y; } } void msort(int l, int r){ if(l >= r - 1) { if(tower[l].x > tower[r].x){ int x, y; x = tower[l].x; y = tower[l].y; tower[l].x = tower[r].x; tower[l].y = tower[r].y; tower[r].x = x; tower[r].y = y; } return; } int mid = (l + r) >> 1; msort(l, mid); msort(mid + 1, r); merg(l, mid, r); } void merge1(int l, int mid, int r) { int i, j; ll cnt = 0; int k = l; i = l; j = mid + 1; while(i <= mid && j <= r){ if(tower[i].y < tower[j].y){ des[k++] = tower[i++].y; cnt += r - j + 1; } else{ des[k++] = tower[j++].y; } } while(i <= mid) des[k++] = tower[i++].y; while(j <= r) des[k++] = tower[j++].y; for (i = l; i <= r; i++){ tower[i].y = des[i]; } num += cnt; } void get_num(int l, int r) { if(l >= r - 1){ if(tower[l].y < tower[r].y){ num++; } else{ int temp = tower[l].y; tower[l].y = tower[r].y; tower[r].y = temp; } return; } int mid = (l + r) >> 1; get_num(l, mid); get_num(mid + 1, r); merge1(l, mid, r); } int main() { scanf("%d", &N); num = 0; for (int i = 0; i < N; i++) { scanf("%lld %lld", &tower[i].x, &tower[i].y); } msort(0, N - 1); get_num(0, N - 1); printf("%lld\n", num); return 0; }