Question 3 Lighthouse (LightHouse)

There are many lighthouses on the sea to illuminate the passing ships.

(Figure 1)
As shown in Figure 1, each lighthouse is equipped with a searchlight to illuminate two right-angled areas on its northeast and southwest sides. Searchlights are powerful enough to cover any distance. The lighthouses themselves are so small, it can be assumed that they do not obscure each other.

(Figure 2)
If both lighthouses A and B are within the illumination range of each other, it is said that they can illuminate each other. For example, in the example in Figure 2, the blue and red lighthouses can illuminate each other, but the blue and green lighthouses are not, and neither are the red and green lighthouses.
Now, for any given set of lighthouses, figure out how many pairs of them are able to illuminate each other.

Input format:
a total of n+1 lines.
The first row contains an integer n, representing the total number of lighthouses.
Lines 2 to n+1 each contain 2 integers x, y, respectively representing the horizontal and vertical coordinates of each lighthouse.

Requirements:
1 ≤ n ≤ 4×10^6
The coordinates x and y of lighthouses are integers, and the x and y coordinates of different lighthouses are different from each other
1 ≤ x, y ≤ 10^8

Output format:
1 integer representing the number of lighthouse pairs that can illuminate each other.

Input sample:
3
2 2
4 3
5 1
Output sample:
The corresponding output is given here. For example:

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

Guess you like

Origin blog.csdn.net/qq_51152918/article/details/126687792