1. 程式人生 > >Tsinghua OJ:燈塔(手排+歸併排序)

Tsinghua OJ:燈塔(手排+歸併排序)

燈塔(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.

描述

海上有許多燈塔,為過路船隻照明。

(圖一)

如圖一所示,每個燈塔都配有一盞探照燈,照亮其東北、西南兩個對頂的直角區域。探照燈的功率之大,足以覆蓋任何距離。燈塔本身是如此之小,可以假定它們不會彼此遮擋。

(圖二)

若燈塔A、B均在對方的照亮範圍內,則稱它們能夠照亮彼此。比如在圖二的例項中,藍、紅燈塔可照亮彼此,藍、綠燈塔則不是,紅、綠燈塔也不是。

現在,對於任何一組給定的燈塔,請計算出其中有多少對燈塔能夠照亮彼此。

輸入

共n+1行。

第1行為1個整數n,表示燈塔的總數。

第2到n+1行每行包含2個整數x, y,分別表示各燈塔的橫、縱座標。

輸出

1個整數,表示可照亮彼此的燈塔對的數量。

樣例

見英文題面

限制

對於90%的測例:1 ≤ n ≤ 3×105

對於95%的測例:1 ≤ n ≤ 106

全部測例:1 ≤ n ≤ 4×106

燈塔的座標x, y是整數,且不同燈塔的x, y座標均互異

1 ≤ x, y ≤ 10^8

時間:2 sec

記憶體:256 MB

這裡歸併排序只能過掉百分之九十五的樣例;

發部落格的目的是儲存自己的歸併模板 具體優化需要用到樹狀陣列
#include<stdio.h>
#define maxn 4000005
struct node
{
	long long x,y;
}a[maxn];
long long s[maxn],ss[maxn],count;
void qsort(node aa[],int l,int r)
{
	if(l<r)
	{
	int x=l,y=r;
	node temp;
	temp.x=aa[x].x;
	temp.y=aa[x].y;
	int  t=aa[x].x;
	while(x<y)
	{
		while(x<y && t<aa[y].x)
			y--;
		a[x].x=a[y].x;
		a[x].y=a[y].y;
		while(x<y && aa[x].x<t)
			x++;
		a[y].x=a[x].x;
		a[y].y=a[x].y;
	}
	a[x].x=temp.x;
	a[x].y=temp.y;
	qsort(aa,l,x-1);
	qsort(aa,x+1,r);
	}
}
void merge(long long *s,long long *ss,int l,int mid,int r)
{
	int i=l,j=mid+1;
	int k=l;
	while(i<=mid && j<=r)
	{
		if(s[i]<s[j])
		{
			ss[k++]=s[i++];
			count+=r-j+1;//求順序對
		}
		else
			ss[k++]=s[j++];
	}
	while(i<=mid)
		ss[k++]=s[i++];
	while(j<=r)
		ss[k++]=s[j++];
	for(i=l;i<=r;i++)
		s[i]=ss[i];
}
void mergesort(long long *s,long long *ss,int l,int r)
{
	int mid=(l+r)/2;
	if(l<r)
	{
		mergesort(s,ss,l,mid);
		mergesort(s,ss,mid+1,r);
		merge(s,ss,l,mid,r);
	}
}
int  main()
{
	int n,i;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
		scanf("%lld%lld",&a[i].x,&a[i].y);
	qsort(a,1,n);
	for(i=1;i<=n;i++)
		s[i]=a[i].y;
	mergesort(s,ss,1,n);
	printf("%lld\n",count);
}