灯塔(LightHouse)

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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值