1. 程式人生 > >【C++實現】LightHouse

【C++實現】LightHouse

燈塔(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
*/