Description
As shown in the following figure, If another lighthouse is in gray area, they can beacon each other.
For example, in following figure, (B, R) is a pair of lighthouse which can beacon each other, while (B, G), (R, G) are NOT.
Input
1st line: N
2nd ~ (N + 1)th line: each line is X Y, means a lighthouse is on the point (X, Y).
Output
How many pairs of lighthourses can beacon each other
( For every lighthouses, X coordinates won't be the same , Y coordinates won't be the same )
Example
Input
3
2 2
4 3
5 1
Output
1
Restrictions
For 90% test cases: 1 <= n <= 3 * 105
For 95% test cases: 1 <= n <= 106
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
Hints
The range of int is usually [-231, 231 - 1], it may be too small.
解答:
将灯塔按照x轴排序,如果两个灯塔不能彼此照亮当且仅当y方向的两个灯塔构成一个逆序对。所以将本问题转换成先将(x,y)坐标序列按照x排序,然后再求按照y坐标这个序列包含的逆序对的个数。
可以用归并排序的思想的框架。程序的时间复杂度为O(nlogn)。代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct location
{
int x, y;
};
location lighthouse[4000005];
int cmp(const void * l1_, const void * l2_)
{
location *l1 = (location *)l1_;
location *l2 = (location *)l2_;
return l1->x - l2->x;
}
long merge(int lo, int mid, int hi);
long cal(int lo, int hi)
{
if(hi - lo < 2)
return 0;
int mid = (lo + hi) >> 1;
long rel = cal(lo, mid);
long rer = cal(mid, hi);
long rem = merge(lo, mid, hi);
return rel + rer + rem;
}
long merge(int lo, int mid, int hi)
{
location * A = lighthouse + lo;
int lb = mid - lo; location * B = new location[lb];
for(int i = 0; i < lb; i++)
{
B[i].x = lighthouse[lo+i].x;
B[i].y = lighthouse[lo+i].y;
}
int lc = hi - mid; location * C = lighthouse + mid;
long insersion = 0;
for(int i = 0, j = 0, k = 0; j < lb; )
{
if(k < lc && B[j].y >= C[k].y)
{
insersion += (lb - j);
A[i].x = C[k].x;
A[i++].y = C[k++].y;
}
if(k >= lc || B[j].y < C[k].y)
{
A[i].x = B[j].x;
A[i++].y = B[j++].y;
}
}
delete[] B;
return insersion;
}
int main()
{
int N, x, y;
scanf("%d", &N);
memset(lighthouse, 0, 4000005 * sizeof(location));
for(int i = 0; i < N; i++)
{
scanf("%d%d", &x, &y);
lighthouse[i].x = x;
lighthouse[i].y = y;
}
qsort(lighthouse, N, sizeof(location), cmp);
long re = (long) N * (N - 1) / 2 - cal(0, N);
printf("%ld\n", re);
return 0;
}