海上有许多灯塔,为过路船只照明。
(图一)
如图一所示,每个灯塔都配有一盏探照灯,照亮其东北、西南两个对顶的直角区域。探照灯的功率之大,足以覆盖任何距离。灯塔本身是如此之小,可以假定它们不会彼此遮挡。
(图二)
若灯塔A、B均在对方的照亮范围内,则称它们能够照亮彼此。比如在图二的实例中,蓝、红灯塔可照亮彼此,蓝、绿灯塔则不是,红、绿灯塔也不是。
现在,对于任何一组给定的灯塔,请计算出其中有多少对灯塔能够照亮彼此。
输入格式:
共n+1行。
第1行为1个整数n,表示灯塔的总数。
第2到n+1行每行包含2个整数x, y,分别表示各灯塔的横、纵坐标。
要求:
1 ≤ n ≤ 4×10^6
灯塔的坐标x, y是整数,且不同灯塔的x, y坐标均互异
1 ≤ x, y ≤ 10^8
输出格式:
1个整数,表示可照亮彼此的灯塔对的数量。
输入样例:
3
2 2
4 3
5 1
输出样例:
在这里给出相应的输出。例如:
1
code:
//本题的逻辑结构:线性
//本题的存储结构:顺序结构
//解题思路和算法:升序快排x坐标,升序归并排序y坐标并求逆序对,答案等于n*(n-1)/2-逆序对数
//效率:时间复杂度O(nlogn)、空间复杂度O(n)
//测试数据:
/*
(1)
输入:
3
2 2
4 3
5 1
输出:
1
*/
#include <bits/stdc++.h>
#define rep(i,a,b) for(auto i=(a);i<=(b);i++)
#define dep(i,a,b) for(auto i=(a);i>=(b);--i)
using namespace std;
typedef long long ll;
const int N = 4e6+10;
ll n;
struct node {
/* 灯塔结构体,存x和y坐标 */
int x,y;
}s[N];
int y[N]; /* 单独存y坐标,用来归并排序 */
int temp[N]; /* 存排序好的y坐标 */
ll cnt; /* 排序前y坐标逆序对数量 */
void MergeArray(int left,int mid,int right); /* 归并排序数组赋值,将当前区间已排序元素复制到temp数组中 */
void MergeSort(int left,int right); /* 归并排序 */
void AC(){
scanf("%lld",&n);
rep(i,1,n){
scanf("%d %d",&s[i].x,&s[i].y);
}
sort(s+1,s+1+n,[&](node a,node b){
return a.x<b.x;}); /* 利用匿名结构体排序函数对灯塔按x坐标升序排序 */
rep(i,1,n){
y[i] = s[i].y; /* 将y坐标另外存到数组中便于归并排序 */
}
MergeSort(1,n); /* 对y进行归并排序并统计逆序对数量 */
printf("%lld\n",n*(n-1)/2-cnt); /* 答案等于次序总数减去逆序对个数(即顺序对个数 */
}
int main(){
int _ = 1;/* 样例组数 */
//scanf("%d",&_);
while(_--){
AC();
}
return 0;
}
void MergeSort(int left,int right){
/* 归并排序 */
if(left >= right)return;
int mid = (left+right)>>1;
MergeSort(left,mid); /* 排序左半部分 */
MergeSort(mid+1,right); /* 排序右半部分 */
MergeArray(left,mid,right); /* 将当前区间已排序元素复制到temp数组中 */
}
void MergeArray(int left,int mid,int right){
/* 将当前区间已排序元素复制到temp数组中 */
int tot = 0; /* temp数组指针 */
int t1 = left; /* 区间左半部分指针 */
int t2 = mid + 1; /* 区间右半部分指针 */
while(t1 <= mid && t2 <= right){
/* 当任意一部分未遍历完 */
if(y[t1] < y[t2]) {
/* 左半部分当前元素小 */
temp[++tot] = y[t1++];
}
else {
/* 右半部分当前元素小 */
temp[++tot] = y[t2++];
cnt += mid-t1+1; /* 统计逆序对数量 */
}
}
while(t1 <= mid) {
/* 遍历左半部分剩下元素 */
temp[++tot] = y[t1++];
}
while(t2 <= right) {
/* 遍历右半部分剩下元素 */
temp[++tot] = y[t2++];
}
rep(i,left,right) {
/* 将已排序好的元素复制到y数组中 */
y[i] = temp[i-left+1];
}
}